diff --git a/src/app.controller.ts b/src/app.controller.ts index 08e392f..24fa193 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,5 +1,4 @@ import { Controller } from '@nestjs/common'; -import { AppService } from './app.service'; @Controller() export class AppController {} diff --git a/src/comment/comment.controller.ts b/src/comment/comment.controller.ts index 3ff18f1..6aa42a2 100644 --- a/src/comment/comment.controller.ts +++ b/src/comment/comment.controller.ts @@ -1,79 +1,115 @@ -import {Controller, Post, Body, Req, UseGuards, Param, Patch, Delete} from '@nestjs/common'; +import { + Controller, + Post, + Body, + Req, + UseGuards, + Param, + Patch, + Delete, +} from '@nestjs/common'; import { CommentService } from './comment.service'; import { CreateCommentDto } from './dto/create-comment.dto'; import { ResponseCode } from '../response/response-code.enum'; import { ResponseDto } from '../response/response.dto'; import { UserGuard } from '../user/user.guard'; import { Request } from 'express'; -import {UserEntity} from "../user/user.entity"; -import {RuleMainEntity} from "../rule/domain/rule.main.entity"; @Controller('mate/rule/detail/comment') export class CommentController { - constructor( - private readonly commentService: CommentService, - ) {} + constructor(private readonly commentService: CommentService) {} // [1] 댓글 작성 @Post('/:ruleId') @UseGuards(UserGuard) - async createComment(@Body() dto: CreateCommentDto, @Param('ruleId') ruleId: number, @Req() req: Request): Promise> { - const result = await this.commentService.createComment(dto, ruleId, req.user.id); + async createComment( + @Body() dto: CreateCommentDto, + @Param('ruleId') ruleId: number, + @Req() req: Request, + ): Promise> { + const result = await this.commentService.createComment( + dto, + ruleId, + req.user.id, + ); - console.log('controller 진입') - if(!result){ + console.log('controller 진입'); + if (!result) { return new ResponseDto( ResponseCode.COMMENT_CREATION_FAIL, false, - "여행 규칙 코멘트 생성 실패", - null); - } - else{ + '여행 규칙 코멘트 생성 실패', + null, + ); + } else { return new ResponseDto( ResponseCode.COMMENT_CREATED, true, - "여행 규칙 코멘트 생성 성공", - result); + '여행 규칙 코멘트 생성 성공', + result, + ); } } // [2] 댓글 수정 @Patch('/:ruleId/:commentId') @UseGuards(UserGuard) - async updateComment(@Body() dto: CreateCommentDto, @Param('ruleId') ruleId: number, @Param('commentId') commentId: number,@Req() req: Request): Promise> { + async updateComment( + @Body() dto: CreateCommentDto, + @Param('ruleId') ruleId: number, + @Param('commentId') commentId: number, + @Req() req: Request, + ): Promise> { try { - const result = await this.commentService.updateComment(dto, ruleId, req.user.id, commentId); + const result = await this.commentService.updateComment( + dto, + ruleId, + req.user.id, + commentId, + ); return new ResponseDto( - ResponseCode.COMMENT_UPDATE_SUCCESS, - true, - "여행 규칙 코멘트 수정 성공", - result); + ResponseCode.COMMENT_UPDATE_SUCCESS, + true, + '여행 규칙 코멘트 수정 성공', + result, + ); } catch (e) { return new ResponseDto( - ResponseCode.COMMENT_UPDATE_FAIL, - false, - e.message, - null); + ResponseCode.COMMENT_UPDATE_FAIL, + false, + e.message, + null, + ); } } // [3] 댓글 삭제 @Delete('/:ruleId/:commentId') @UseGuards(UserGuard) - async deleteComment(@Param('ruleId') ruleId: number, @Param('commentId') commentId: number,@Req() req: Request): Promise> { + async deleteComment( + @Param('ruleId') ruleId: number, + @Param('commentId') commentId: number, + @Req() req: Request, + ): Promise> { try { - const result = await this.commentService.deleteComment(ruleId, req.user.id, commentId); + const result = await this.commentService.deleteComment( + ruleId, + req.user.id, + commentId, + ); return new ResponseDto( - ResponseCode.COMMENT_DELETE_SUCCESS, - true, - "여행 규칙 코멘트 삭제 성공", - result); + ResponseCode.COMMENT_DELETE_SUCCESS, + true, + '여행 규칙 코멘트 삭제 성공', + result, + ); } catch (e) { return new ResponseDto( - ResponseCode.COMMENT_DELETE_FAIL, - false, - e.message, - null); + ResponseCode.COMMENT_DELETE_FAIL, + false, + e.message, + null, + ); } } -} \ No newline at end of file +} diff --git a/src/comment/comment.service.ts b/src/comment/comment.service.ts index 0ed863f..acb25f2 100644 --- a/src/comment/comment.service.ts +++ b/src/comment/comment.service.ts @@ -1,29 +1,32 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { CreateCommentDto } from './dto/create-comment.dto'; import { CommentEntity } from './domain/comment.entity'; -import {RuleMainEntity} from "../rule/domain/rule.main.entity"; -import {UserEntity} from "../user/user.entity"; +import { RuleMainEntity } from '../rule/domain/rule.main.entity'; +import { UserEntity } from '../user/user.entity'; import { NotificationEntity } from '../notification/notification.entity'; -import { NotificationService } from '../notification/notification.service'; @Injectable() export class CommentService { - // [1] 댓글 작성 - async createComment(dto: CreateCommentDto, ruleId: number, userId: number): Promise { - + async createComment( + dto: CreateCommentDto, + ruleId: number, + userId: number, + ): Promise { const comment = new CommentEntity(); const user = await UserEntity.findOneOrFail({ where: { id: userId } }); - const rule = await RuleMainEntity.findOneOrFail({ where: { id: ruleId }, relations: { invitations: { member: true } } }); + const rule = await RuleMainEntity.findOneOrFail({ + where: { id: ruleId }, + relations: { invitations: { member: true } }, + }); - if(!user || !rule){ + if (!user || !rule) { throw new Error('Data not found'); - } - else{ - console.log("user name: "+ user.name); + } else { + console.log('user name: ' + user.name); comment.user = user; - console.log("rule id: "+ rule.id); + console.log('rule id: ' + rule.id); comment.rule = rule; comment.content = dto.content; await comment.save(); @@ -48,25 +51,30 @@ export class CommentService { } // [2] 댓글 수정 - async updateComment(dto: CreateCommentDto, ruleId: number, userId: number, commentId: number) : Promise { + async updateComment( + dto: CreateCommentDto, + ruleId: number, + userId: number, + commentId: number, + ): Promise { try { // 사용자, 규칙, 댓글 검증 const user = await UserEntity.findOne({ - where: {id : userId}, + where: { id: userId }, }); if (!user) throw new NotFoundException('사용자를 찾을 수 없습니다'); const rule = await RuleMainEntity.findOne({ - where: {id: ruleId}, - }) + where: { id: ruleId }, + }); if (!rule) throw new NotFoundException('존재하지 않는 규칙입니다'); const comment = await CommentEntity.findOne({ - where: {id: commentId} + where: { id: commentId }, }); if (!comment) throw new NotFoundException('존재하지 않는 댓글 입니다'); const checkValidateUser = await CommentEntity.findOne({ - where: {id: commentId, user: {id: userId}, rule: {id: ruleId}}} - ) + where: { id: commentId, user: { id: userId }, rule: { id: ruleId } }, + }); if (!!checkValidateUser) { comment.content = dto.content; await CommentEntity.save(comment); @@ -81,26 +89,30 @@ export class CommentService { } // [3] 댓글 삭제 - async deleteComment(ruleId: number, userId: number, commentId: number) : Promise { + async deleteComment( + ruleId: number, + userId: number, + commentId: number, + ): Promise { try { // 사용자, 규칙, 댓글 검증 const user = await UserEntity.findOne({ - where: {id : userId}, + where: { id: userId }, }); if (!user) throw new NotFoundException('사용자를 찾을 수 없습니다'); const rule = await RuleMainEntity.findOne({ - where: {id: ruleId}, - }) + where: { id: ruleId }, + }); if (!rule) throw new NotFoundException('존재하지 않는 규칙입니다'); const comment = await CommentEntity.findOne({ - where: {id: commentId} + where: { id: commentId }, }); if (!comment) throw new NotFoundException('존재하지 않는 댓글 입니다'); // 해당 규칙에, 해당 사용자가 작성한, 해당 댓글 ID를 가진 댓글이 있는지 검증 const checkValidateUser = await CommentEntity.findOne({ - where: {id: commentId, user: {id: userId}, rule: {id: ruleId}}} - ) + where: { id: commentId, user: { id: userId }, rule: { id: ruleId } }, + }); if (!!checkValidateUser) { await comment.softRemove(); console.log('댓글 삭제 성공'); diff --git a/src/comment/domain/comment.entity.ts b/src/comment/domain/comment.entity.ts index 112d4ab..800ed26 100644 --- a/src/comment/domain/comment.entity.ts +++ b/src/comment/domain/comment.entity.ts @@ -7,7 +7,7 @@ import { JoinColumn, CreateDateColumn, UpdateDateColumn, - DeleteDateColumn + DeleteDateColumn, } from 'typeorm'; import { RuleMainEntity } from 'src/rule/domain/rule.main.entity'; import { UserEntity } from 'src/user/user.entity'; @@ -20,12 +20,12 @@ export class CommentEntity extends BaseEntity { @Column({ type: 'varchar', length: 200 }) content: string; - @ManyToOne(() => RuleMainEntity, ruleMain => ruleMain.comments) - @JoinColumn({ name: 'rule_id'}) + @ManyToOne(() => RuleMainEntity, (ruleMain) => ruleMain.comments) + @JoinColumn({ name: 'rule_id' }) rule: RuleMainEntity; - @ManyToOne(() => UserEntity, user => user.comments) - @JoinColumn({ name: 'user_id'}) + @ManyToOne(() => UserEntity, (user) => user.comments) + @JoinColumn({ name: 'user_id' }) user: UserEntity; @CreateDateColumn() @@ -36,4 +36,4 @@ export class CommentEntity extends BaseEntity { @DeleteDateColumn() deleted: Date; -} \ No newline at end of file +} diff --git a/src/comment/dto/create-comment.dto.ts b/src/comment/dto/create-comment.dto.ts index 8fd8ba2..f9b0981 100644 --- a/src/comment/dto/create-comment.dto.ts +++ b/src/comment/dto/create-comment.dto.ts @@ -1,7 +1,7 @@ import { IsNotEmpty, IsString } from 'class-validator'; export class CreateCommentDto { - @IsNotEmpty() - @IsString() - content: string; -} \ No newline at end of file + @IsNotEmpty() + @IsString() + content: string; +} diff --git a/src/detail-schedule/detail-schedule.controller.ts b/src/detail-schedule/detail-schedule.controller.ts index 024606b..58516cb 100644 --- a/src/detail-schedule/detail-schedule.controller.ts +++ b/src/detail-schedule/detail-schedule.controller.ts @@ -12,10 +12,7 @@ import { import { ApiOkResponse, ApiOperation } from '@nestjs/swagger'; import { Request } from 'express'; import { DetailScheduleService } from './detail-schedule.service'; -import { - DetailContentDto, - DetailScheduleInfoDto, -} from './detail-schedule-info.dto'; +import { DetailContentDto } from './detail-schedule-info.dto'; import { UserGuard } from 'src/user/user.guard'; @Controller('detail-schedule') diff --git a/src/detail-schedule/detail-schedule.entity.ts b/src/detail-schedule/detail-schedule.entity.ts index ccccfeb..44d7c38 100644 --- a/src/detail-schedule/detail-schedule.entity.ts +++ b/src/detail-schedule/detail-schedule.entity.ts @@ -4,7 +4,6 @@ import { CreateDateColumn, DeleteDateColumn, Entity, - JoinColumn, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn, @@ -12,10 +11,7 @@ import { import { NotFoundException } from '@nestjs/common'; import { BaseResponse } from 'src/response/response.status'; import { ScheduleEntity } from '../schedule/schedule.entity'; -import { - DetailContentDto, - DetailScheduleInfoDto, -} from './detail-schedule-info.dto'; +import { DetailContentDto } from './detail-schedule-info.dto'; @Entity() export class DetailScheduleEntity extends BaseEntity { diff --git a/src/detail-schedule/detail-schedule.service.ts b/src/detail-schedule/detail-schedule.service.ts index 50a3eae..241ff4e 100644 --- a/src/detail-schedule/detail-schedule.service.ts +++ b/src/detail-schedule/detail-schedule.service.ts @@ -11,10 +11,7 @@ export class DetailScheduleService { async createDetailSchedule(scheduleId: number, content: DetailContentDto) { const schedule = await ScheduleEntity.findExistSchedule(scheduleId); console.log(schedule.id); - const detailSchedule = await DetailScheduleEntity.createDetailSchedule( - schedule, - content, - ); + await DetailScheduleEntity.createDetailSchedule(schedule, content); return response(BaseResponse.DETAIL_SCHEDULE_CREATED); } @@ -45,8 +42,7 @@ export class DetailScheduleService { //세부일정 삭제하기 async deleteDetailSchedule(detailId: number) { const detailSchedule = await DetailScheduleEntity.findExistDetail(detailId); - const deleteDetailSchedule = - await DetailScheduleEntity.deleteDetailSchedule(detailSchedule); + await DetailScheduleEntity.deleteDetailSchedule(detailSchedule); return response(BaseResponse.DELETE_DETAIL_SCHEDULE_SUCCESS); } } diff --git a/src/diary/models/diary.image.entity.ts b/src/diary/models/diary.image.entity.ts index c9ab3f6..b39a49c 100644 --- a/src/diary/models/diary.image.entity.ts +++ b/src/diary/models/diary.image.entity.ts @@ -10,7 +10,6 @@ import { UpdateDateColumn, } from 'typeorm'; import { DiaryEntity } from './diary.entity'; -import { S3UtilService } from 'src/utils/S3.service'; @Entity() export class DiaryImageEntity extends BaseEntity { diff --git a/src/follow/dto/follow.dto.ts b/src/follow/dto/follow.dto.ts index 9c154b6..82a206f 100644 --- a/src/follow/dto/follow.dto.ts +++ b/src/follow/dto/follow.dto.ts @@ -1,27 +1,33 @@ -import {IsBoolean, IsNotEmpty, IsNumber, IsOptional, IsString} from 'class-validator'; +import { + IsBoolean, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; export class FollowDto { - @IsNotEmpty() - @IsNumber() - mateId: number; + @IsNotEmpty() + @IsNumber() + mateId: number; - @IsNotEmpty() - @IsString() - nickName: string; + @IsNotEmpty() + @IsString() + nickName: string; - @IsNotEmpty() - @IsString() - email: string; + @IsNotEmpty() + @IsString() + email: string; - @IsOptional() - @IsString() - image: string; + @IsOptional() + @IsString() + image: string; - @IsOptional() - @IsString() - introduction: string; + @IsOptional() + @IsString() + introduction: string; - @IsNotEmpty() - @IsBoolean() - isFollowing: boolean; -} \ No newline at end of file + @IsNotEmpty() + @IsBoolean() + isFollowing: boolean; +} diff --git a/src/follow/dto/follow.search.dto.ts b/src/follow/dto/follow.search.dto.ts index 06cbe00..108e28f 100644 --- a/src/follow/dto/follow.search.dto.ts +++ b/src/follow/dto/follow.search.dto.ts @@ -1,31 +1,37 @@ -import {IsBoolean, IsNotEmpty, IsNumber, IsOptional, IsString} from 'class-validator'; +import { + IsBoolean, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; export class FollowSearchDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - nickName: string; + @IsNotEmpty() + @IsString() + nickName: string; - @IsOptional() - @IsString() - introduction: string; + @IsOptional() + @IsString() + introduction: string; - @IsNotEmpty() - @IsString() - followerCnt: number; + @IsNotEmpty() + @IsString() + followerCnt: number; - @IsOptional() - @IsString() - followingCnt: number; + @IsOptional() + @IsString() + followingCnt: number; - @IsOptional() - @IsString() - image: string; + @IsOptional() + @IsString() + image: string; - @IsOptional() - @IsBoolean() - isFollowing: boolean; -} \ No newline at end of file + @IsOptional() + @IsBoolean() + isFollowing: boolean; +} diff --git a/src/follow/follow.controller.ts b/src/follow/follow.controller.ts index d3010da..923ddba 100644 --- a/src/follow/follow.controller.ts +++ b/src/follow/follow.controller.ts @@ -1,115 +1,129 @@ -import {Controller, Req, UseGuards, Param, Get, Patch, Query} from '@nestjs/common'; +import { + Controller, + Req, + UseGuards, + Param, + Get, + Patch, + Query, +} from '@nestjs/common'; import { FollowService } from './follow.service'; import { ResponseCode } from '../response/response-code.enum'; import { ResponseDto } from '../response/response.dto'; import { UserGuard } from '../user/user.guard'; -import { Request} from 'express'; -import {CursorPageOptionsDto} from "../rule/dto/cursor-page.options.dto"; +import { Request } from 'express'; +import { CursorPageOptionsDto } from '../rule/dto/cursor-page.options.dto'; @Controller('mate/follow') export class FollowController { - constructor( - private readonly followService: FollowService, - ) {} + constructor(private readonly followService: FollowService) {} - // [1] 메이트 검색 - 무한 스크롤 적용 - @Get('/search') - @UseGuards(UserGuard) - async getSearchResult( - @Query('searchTerm')searchTerm : string, - @Query() cursorPageOptionsDto: CursorPageOptionsDto, - @Req() req: Request): Promise> { - try { - const result = await this.followService.getSearchResult(cursorPageOptionsDto, req.user.id, searchTerm); - return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_SUCCESS, - true, - "검색 결과 리스트 불러오기 성공", - result - ); - } catch (error) { - return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_FAIL, - false, - "검색 결과 리스트 불러오기 실패", - null - ); - } + // [1] 메이트 검색 - 무한 스크롤 적용 + @Get('/search') + @UseGuards(UserGuard) + async getSearchResult( + @Query('searchTerm') searchTerm: string, + @Query() cursorPageOptionsDto: CursorPageOptionsDto, + @Req() req: Request, + ): Promise> { + try { + const result = await this.followService.getSearchResult( + cursorPageOptionsDto, + req.user.id, + searchTerm, + ); + return new ResponseDto( + ResponseCode.GET_SEARCH_RESULT_SUCCESS, + true, + '검색 결과 리스트 불러오기 성공', + result, + ); + } catch (error) { + return new ResponseDto( + ResponseCode.GET_SEARCH_RESULT_FAIL, + false, + '검색 결과 리스트 불러오기 실패', + null, + ); } + } - // [2] 팔로워 리스트 조회 - @Get('/followerList') - @UseGuards(UserGuard) - async getFollowerList(@Req() req: Request): Promise> { - try { - const followerList = await this.followService.getFollowerList(req.user.id); - return new ResponseDto( - ResponseCode.GET_FOLLOWER_LIST_SUCCESS, - true, - "팔로워 리스트 불러오기 성공", - followerList - ); - } catch (e) { - return new ResponseDto( - ResponseCode.GET_FOLLOWER_LIST_FAIL, - false, - e.message, - null - ); - } + // [2] 팔로워 리스트 조회 + @Get('/followerList') + @UseGuards(UserGuard) + async getFollowerList(@Req() req: Request): Promise> { + try { + const followerList = await this.followService.getFollowerList( + req.user.id, + ); + return new ResponseDto( + ResponseCode.GET_FOLLOWER_LIST_SUCCESS, + true, + '팔로워 리스트 불러오기 성공', + followerList, + ); + } catch (e) { + return new ResponseDto( + ResponseCode.GET_FOLLOWER_LIST_FAIL, + false, + e.message, + null, + ); } + } - // [3] 팔로우 리스트 조회 - @Get('/followList') - @UseGuards(UserGuard) - async getFollowList(@Req() req: Request): Promise> { - console.log('controller'); - try { - const followList = await this.followService.getFollowList(req.user.id); - return new ResponseDto( - ResponseCode.GET_FOLLOWING_LIST_SUCCESS, - true, - "팔로우 리스트 불러오기 성공", - followList - ); - } catch (e) { - return new ResponseDto( - ResponseCode.GET_FOLLOWING_LIST_FAIL, - false, - e.message, - null - ); - } + // [3] 팔로우 리스트 조회 + @Get('/followList') + @UseGuards(UserGuard) + async getFollowList(@Req() req: Request): Promise> { + console.log('controller'); + try { + const followList = await this.followService.getFollowList(req.user.id); + return new ResponseDto( + ResponseCode.GET_FOLLOWING_LIST_SUCCESS, + true, + '팔로우 리스트 불러오기 성공', + followList, + ); + } catch (e) { + return new ResponseDto( + ResponseCode.GET_FOLLOWING_LIST_FAIL, + false, + e.message, + null, + ); } + } - // [4] 팔로우 - @Patch('/:followingId') - @UseGuards(UserGuard) - async createFollow(@Req() req: Request, @Param('followingId') followingId : number): Promise> { - try { - const result = await this.followService.checkFollow(req.user.id, followingId); - if (!!result.deleted) { - return new ResponseDto( - ResponseCode.FOLLOW_SUCCESS, - true, - "언팔로우 성공", - result.id - ); - } else { - return new ResponseDto( - ResponseCode.FOLLOW_SUCCESS, - true, - "팔로우 성공", - result.id - ); - } - } catch (e) { - return new ResponseDto( - ResponseCode.FOLLOW_FAIL, - false, - e.message, - null - ); - } + // [4] 팔로우 + @Patch('/:followingId') + @UseGuards(UserGuard) + async createFollow( + @Req() req: Request, + @Param('followingId') followingId: number, + ): Promise> { + try { + const result = await this.followService.checkFollow( + req.user.id, + followingId, + ); + if (!!result.deleted) { + return new ResponseDto( + ResponseCode.FOLLOW_SUCCESS, + true, + '언팔로우 성공', + result.id, + ); + } else { + return new ResponseDto( + ResponseCode.FOLLOW_SUCCESS, + true, + '팔로우 성공', + result.id, + ); + } + } catch (e) { + return new ResponseDto(ResponseCode.FOLLOW_FAIL, false, e.message, null); } -} \ No newline at end of file + } +} diff --git a/src/follow/follow.service.ts b/src/follow/follow.service.ts index 4468d94..afd4f5e 100644 --- a/src/follow/follow.service.ts +++ b/src/follow/follow.service.ts @@ -1,274 +1,322 @@ -import {Injectable, HttpException, NotFoundException, BadRequestException} from '@nestjs/common'; +import { + Injectable, + NotFoundException, + BadRequestException, +} from '@nestjs/common'; import { UserFollowingEntity } from 'src/user/user.following.entity'; import { FollowDto } from './dto/follow.dto'; -import { UserEntity } from "../user/user.entity"; -import { UserService } from "../user/user.service"; -import { S3UtilService } from "../utils/S3.service"; -import {LessThan, Like} from "typeorm"; -import {FollowSearchDto} from "./dto/follow.search.dto"; -import {CursorPageOptionsDto} from "../rule/dto/cursor-page.options.dto"; -import {CursorPageMetaDto} from "../rule/dto/cursor-page.meta.dto"; -import {CursorPageDto} from "../rule/dto/cursor-page.dto"; +import { UserEntity } from '../user/user.entity'; +import { UserService } from '../user/user.service'; +import { S3UtilService } from '../utils/S3.service'; +import { LessThan, Like } from 'typeorm'; +import { FollowSearchDto } from './dto/follow.search.dto'; +import { CursorPageOptionsDto } from '../rule/dto/cursor-page.options.dto'; +import { CursorPageMetaDto } from '../rule/dto/cursor-page.meta.dto'; +import { CursorPageDto } from '../rule/dto/cursor-page.dto'; @Injectable() export class FollowService { - constructor( - private readonly userService: UserService, - private readonly s3Service: S3UtilService, - ) {} - - // [1] 메이트 검색 - async getSearchResult(cursorPageOptionsDto: CursorPageOptionsDto, userId: number, searchTerm: string) { - - try { - // 검증1) 사용자가 존재하지 않는 경우 - const userEntity = await UserEntity.findOne({ - where: { - id: userId, - }, - }); - if (!userEntity) throw new Error('사용자를 찾을 수 없습니다'); - - let cursorId: number = 0; - - // (1) cursorId 설정 - // -1) 처음 요청인 경우 - if (cursorPageOptionsDto.cursorId == 0) { - const newUser = await UserEntity.find({ - order: { - id: 'DESC' // 가장 최근에 가입한 유저 - }, - take: 1 - }); - cursorId = newUser[0].id + 1; - - console.log('cursorPageOptionsDto.cursorId == 0 로 인식'); - console.log('cursor: ', cursorId); - // -2) 처음 요청이 아닌 경우 - } else { - cursorId = cursorPageOptionsDto.cursorId; - console.log('cursorPageOptionsDto.cursorId != 0 로 인식') - } - console.log('cursor: ', cursorId); - - // (2) 데이터 조회 - // 검색 결과에 해당하는 값 찾기 - // 해당 결과값을 nickName 에 포함하고 있는 사용자 찾기 - - console.log('검색 값: ', searchTerm); - - // take 초기값 설정 - console.log('cursorPageOptionsDto.take : ', cursorPageOptionsDto.take); - if (cursorPageOptionsDto.take == 0) { - cursorPageOptionsDto.take = 5; - } - - const [resultUsers, total] = await UserEntity.findAndCount({ - take: cursorPageOptionsDto.take, - where: [ - { - id: cursorId ? LessThan(cursorId) : null, - isQuit: false, - nickname: Like(`%${searchTerm}%`), - } - ], - relations: {profileImage : true, follower : true, following : true}, - order: { - id: "DESC" as any, - }, - }); - - const searchResult = await Promise.all(resultUsers.map(async (user) => { - const followSearchDto = new FollowSearchDto(); - - console.log('현재의 유저 : ', user.id); - followSearchDto.id = user.id; - followSearchDto.nickName = user.nickname; - followSearchDto.introduction = user.introduction; - - followSearchDto.followerCnt = user.follower.length; - followSearchDto.followingCnt = user.following.length; - - // 팔로우 여부 - followSearchDto.isFollowing = await this.userService.checkIfFollowing(userEntity, followSearchDto.id); - - // 사용자 프로필 이미지 - const image = user.profileImage; - if(image == null) followSearchDto.image = null; - else{ - const userImageKey = image.imageKey; - followSearchDto.image = await this.s3Service.getImageUrl(userImageKey); - } - return followSearchDto; - })); - - // (3) 페이징 및 정렬 기준 설정 - let hasNextData = true; - let cursor: number; - - const takePerScroll = cursorPageOptionsDto.take; - const isLastScroll = total <= takePerScroll; - const lastDataPerScroll = resultUsers[resultUsers.length - 1]; - - if (isLastScroll) { - hasNextData = false; - cursor = null; - } else { - cursor = lastDataPerScroll.id; - } - - const cursorPageMetaDto = new CursorPageMetaDto({ cursorPageOptionsDto, total, hasNextData, cursor }); - - return new CursorPageDto(searchResult, cursorPageMetaDto); - } catch (e) { - throw new Error(e.message); - } - } - - // [2] 팔로우 리스트 조회 - async getFollowList(userId: number): Promise { - // 현재 로그인한 사용자 - const user : UserEntity = await this.userService.findUserById(userId); - console.log('현재 로그인한 사용자 : ',user.id); - - // 로그인한 사용자 = 팔로우하는 user - const follows : UserFollowingEntity[] = await this.userService.getFollowingList(userId); - - // 팔로우 사용자들 정보 리스트 - const informs = await Promise.all(follows.map(async (follow) => { - const followDto : FollowDto = new FollowDto(); - const mateEntity : UserEntity = follow.followUser; - console.log('팔로우 사용자의 ID : ', mateEntity.id); - - followDto.nickName = mateEntity.nickname; - followDto.mateId = mateEntity.id; - followDto.email = mateEntity.email; - followDto.introduction = mateEntity.introduction; - followDto.isFollowing = !!follow.id; - - // 사용자 프로필 이미지 - const image = await this.userService.getProfileImage(mateEntity.id); - if(image == null) followDto.image = null; - else{ - const userImageKey = image.imageKey; - followDto.image = await this.s3Service.getImageUrl(userImageKey); - } - - return followDto; - })); - return informs; - } - - // [3] 팔로워 리스트 조회 - async getFollowerList(userId: number): Promise { - // 현재 로그인한 사용자 - const user : UserEntity = await this.userService.findUserById(userId); - console.log('현재 로그인한 사용자 : ',user.id); - - // 로그인한 사용자 = 팔로워 - const follows : UserFollowingEntity[] = await this.userService.getFollowerList(userId); - - // 팔로워 사용자들 정보 리스트 - const informs = await Promise.all(follows.map(async (follow) => { - const followDto : FollowDto = new FollowDto(); - const mateEntity : UserEntity = follow.user; - console.log('팔로워 사용자 ID : ', mateEntity.id); - - followDto.nickName = mateEntity.nickname; - followDto.mateId = mateEntity.id; - followDto.email = mateEntity.email; - followDto.introduction = mateEntity.introduction; - followDto.isFollowing = await this.userService.checkIfFollowing(user,mateEntity.id); - - // 사용자 프로필 이미지 - const image = await this.userService.getProfileImage(mateEntity.id); - if(image == null) followDto.image = null; - else{ - const userImageKey = image.imageKey; - followDto.image = await this.s3Service.getImageUrl(userImageKey); - } - return followDto; - })); - - return informs; + constructor( + private readonly userService: UserService, + private readonly s3Service: S3UtilService, + ) {} + + // [1] 메이트 검색 + async getSearchResult( + cursorPageOptionsDto: CursorPageOptionsDto, + userId: number, + searchTerm: string, + ) { + try { + // 검증1) 사용자가 존재하지 않는 경우 + const userEntity = await UserEntity.findOne({ + where: { + id: userId, + }, + }); + if (!userEntity) throw new Error('사용자를 찾을 수 없습니다'); + + let cursorId = 0; + + // (1) cursorId 설정 + // -1) 처음 요청인 경우 + if (cursorPageOptionsDto.cursorId == 0) { + const newUser = await UserEntity.find({ + order: { + id: 'DESC', // 가장 최근에 가입한 유저 + }, + take: 1, + }); + cursorId = newUser[0].id + 1; + + console.log('cursorPageOptionsDto.cursorId == 0 로 인식'); + console.log('cursor: ', cursorId); + // -2) 처음 요청이 아닌 경우 + } else { + cursorId = cursorPageOptionsDto.cursorId; + console.log('cursorPageOptionsDto.cursorId != 0 로 인식'); + } + console.log('cursor: ', cursorId); + + // (2) 데이터 조회 + // 검색 결과에 해당하는 값 찾기 + // 해당 결과값을 nickName 에 포함하고 있는 사용자 찾기 + + console.log('검색 값: ', searchTerm); + + // take 초기값 설정 + console.log('cursorPageOptionsDto.take : ', cursorPageOptionsDto.take); + if (cursorPageOptionsDto.take == 0) { + cursorPageOptionsDto.take = 5; + } + + const [resultUsers, total] = await UserEntity.findAndCount({ + take: cursorPageOptionsDto.take, + where: [ + { + id: cursorId ? LessThan(cursorId) : null, + isQuit: false, + nickname: Like(`%${searchTerm}%`), + }, + ], + relations: { profileImage: true, follower: true, following: true }, + order: { + id: 'DESC' as any, + }, + }); + + const searchResult = await Promise.all( + resultUsers.map(async (user) => { + const followSearchDto = new FollowSearchDto(); + + console.log('현재의 유저 : ', user.id); + followSearchDto.id = user.id; + followSearchDto.nickName = user.nickname; + followSearchDto.introduction = user.introduction; + + followSearchDto.followerCnt = user.follower.length; + followSearchDto.followingCnt = user.following.length; + + // 팔로우 여부 + followSearchDto.isFollowing = await this.userService.checkIfFollowing( + userEntity, + followSearchDto.id, + ); + + // 사용자 프로필 이미지 + const image = user.profileImage; + if (image == null) followSearchDto.image = null; + else { + const userImageKey = image.imageKey; + followSearchDto.image = await this.s3Service.getImageUrl( + userImageKey, + ); + } + return followSearchDto; + }), + ); + + // (3) 페이징 및 정렬 기준 설정 + let hasNextData = true; + let cursor: number; + + const takePerScroll = cursorPageOptionsDto.take; + const isLastScroll = total <= takePerScroll; + const lastDataPerScroll = resultUsers[resultUsers.length - 1]; + + if (isLastScroll) { + hasNextData = false; + cursor = null; + } else { + cursor = lastDataPerScroll.id; + } + + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); + + return new CursorPageDto(searchResult, cursorPageMetaDto); + } catch (e) { + throw new Error(e.message); } - - // [4] 팔로우 가능한 사이인지 검증 - async checkFollow(userId : number, followingId : number): Promise { - try { - // case1) 유효한 유저인지 검증 - const userEntity : UserEntity = await UserEntity.findOne({ - where: {id: userId} - }); - if(!userEntity) throw new NotFoundException('요청을 보낸 사용자를 찾을 수 없습니다') - const followingUser = await UserEntity.findOne({ - where: { - id: followingId - } - }); - if (followingUser.isQuit == true) throw new BadRequestException('탈퇴한 회원 입니다'); - if (!followingUser) throw new NotFoundException('대상 사용자를 찾을 수 없습니다'); - console.log('현재 로그인한 유저 : ', userEntity); - console.log('팔로우 대상 유저 : ', followingUser); - - // case2) 본인을 팔로우한 경우 - if (userId == followingId) throw new BadRequestException('본인을 팔로우 할 수 없습니다'); - - // case3) 팔로우 관계 확인 - const isAlreadyFollowing = await this.userService.isAlreadyFollowing(userId, followingId); - console.log('Is already following? : ', isAlreadyFollowing); - - // [2] 이미 팔로우 한 사이, 팔로우 취소 - if (isAlreadyFollowing) { - console.log('언팔로우 service 호출'); - return this.deleteFollow(userId, followingId); - } else { - // [1] 팔로우 - console.log('팔로우 service 호출'); - return this.createFollow(userId, followingId); - } - } catch (e) { - console.log('팔로우 요청에 실패하였습니다'); - throw new Error(e.message); + } + + // [2] 팔로우 리스트 조회 + async getFollowList(userId: number): Promise { + // 현재 로그인한 사용자 + const user: UserEntity = await this.userService.findUserById(userId); + console.log('현재 로그인한 사용자 : ', user.id); + + // 로그인한 사용자 = 팔로우하는 user + const follows: UserFollowingEntity[] = + await this.userService.getFollowingList(userId); + + // 팔로우 사용자들 정보 리스트 + const informs = await Promise.all( + follows.map(async (follow) => { + const followDto: FollowDto = new FollowDto(); + const mateEntity: UserEntity = follow.followUser; + console.log('팔로우 사용자의 ID : ', mateEntity.id); + + followDto.nickName = mateEntity.nickname; + followDto.mateId = mateEntity.id; + followDto.email = mateEntity.email; + followDto.introduction = mateEntity.introduction; + followDto.isFollowing = !!follow.id; + + // 사용자 프로필 이미지 + const image = await this.userService.getProfileImage(mateEntity.id); + if (image == null) followDto.image = null; + else { + const userImageKey = image.imageKey; + followDto.image = await this.s3Service.getImageUrl(userImageKey); } - } - // [4-1] 팔로우 - async createFollow(userId : number, followingId : number): Promise { - - try { - const userEntity : UserEntity = await this.userService.findUserById(userId); - const followingUser = await UserEntity.findExistUser(followingId); - if (!followingUser) throw new NotFoundException('해당 사용자를 찾을 수 없습니다'); - console.log('현재 로그인한 유저 : ', userEntity); - console.log('팔로우 대상 유저 : ', followingUser); - if (userId == followingId) throw new BadRequestException('본인을 팔로우 할 수 없습니다'); - - const userFollowingEntity = new UserFollowingEntity(); - userFollowingEntity.user = userEntity; - userFollowingEntity.followUser = followingUser; - - await userFollowingEntity.save(); - return userFollowingEntity; - } catch (e) { - console.log('팔로우 요청에 실패하였습니다'); - throw new Error(e.message); + return followDto; + }), + ); + return informs; + } + + // [3] 팔로워 리스트 조회 + async getFollowerList(userId: number): Promise { + // 현재 로그인한 사용자 + const user: UserEntity = await this.userService.findUserById(userId); + console.log('현재 로그인한 사용자 : ', user.id); + + // 로그인한 사용자 = 팔로워 + const follows: UserFollowingEntity[] = + await this.userService.getFollowerList(userId); + + // 팔로워 사용자들 정보 리스트 + const informs = await Promise.all( + follows.map(async (follow) => { + const followDto: FollowDto = new FollowDto(); + const mateEntity: UserEntity = follow.user; + console.log('팔로워 사용자 ID : ', mateEntity.id); + + followDto.nickName = mateEntity.nickname; + followDto.mateId = mateEntity.id; + followDto.email = mateEntity.email; + followDto.introduction = mateEntity.introduction; + followDto.isFollowing = await this.userService.checkIfFollowing( + user, + mateEntity.id, + ); + + // 사용자 프로필 이미지 + const image = await this.userService.getProfileImage(mateEntity.id); + if (image == null) followDto.image = null; + else { + const userImageKey = image.imageKey; + followDto.image = await this.s3Service.getImageUrl(userImageKey); } + return followDto; + }), + ); + + return informs; + } + + // [4] 팔로우 가능한 사이인지 검증 + async checkFollow( + userId: number, + followingId: number, + ): Promise { + try { + // case1) 유효한 유저인지 검증 + const userEntity: UserEntity = await UserEntity.findOne({ + where: { id: userId }, + }); + if (!userEntity) + throw new NotFoundException('요청을 보낸 사용자를 찾을 수 없습니다'); + const followingUser = await UserEntity.findOne({ + where: { + id: followingId, + }, + }); + if (followingUser.isQuit == true) + throw new BadRequestException('탈퇴한 회원 입니다'); + if (!followingUser) + throw new NotFoundException('대상 사용자를 찾을 수 없습니다'); + console.log('현재 로그인한 유저 : ', userEntity); + console.log('팔로우 대상 유저 : ', followingUser); + + // case2) 본인을 팔로우한 경우 + if (userId == followingId) + throw new BadRequestException('본인을 팔로우 할 수 없습니다'); + + // case3) 팔로우 관계 확인 + const isAlreadyFollowing = await this.userService.isAlreadyFollowing( + userId, + followingId, + ); + console.log('Is already following? : ', isAlreadyFollowing); + + // [2] 이미 팔로우 한 사이, 팔로우 취소 + if (isAlreadyFollowing) { + console.log('언팔로우 service 호출'); + return this.deleteFollow(userId, followingId); + } else { + // [1] 팔로우 + console.log('팔로우 service 호출'); + return this.createFollow(userId, followingId); + } + } catch (e) { + console.log('팔로우 요청에 실패하였습니다'); + throw new Error(e.message); } - - // [4-2] 언팔로우 - async deleteFollow(userId: number, followingId:number): Promise { - console.log('언팔로우 서비스 호출'); - const followEntity : UserFollowingEntity = await UserFollowingEntity.findOneOrFail({ where: - { user : {id : userId}, followUser : {id : followingId}} - }); - - try{ - await followEntity.softRemove(); - return followEntity; - }catch(e){ - console.error('언팔로우 요청에 실패하였습니다: '); - throw new Error(e.message); - } + } + + // [4-1] 팔로우 + async createFollow( + userId: number, + followingId: number, + ): Promise { + try { + const userEntity: UserEntity = await this.userService.findUserById( + userId, + ); + const followingUser = await UserEntity.findExistUser(followingId); + if (!followingUser) + throw new NotFoundException('해당 사용자를 찾을 수 없습니다'); + console.log('현재 로그인한 유저 : ', userEntity); + console.log('팔로우 대상 유저 : ', followingUser); + if (userId == followingId) + throw new BadRequestException('본인을 팔로우 할 수 없습니다'); + + const userFollowingEntity = new UserFollowingEntity(); + userFollowingEntity.user = userEntity; + userFollowingEntity.followUser = followingUser; + + await userFollowingEntity.save(); + return userFollowingEntity; + } catch (e) { + console.log('팔로우 요청에 실패하였습니다'); + throw new Error(e.message); + } + } + + // [4-2] 언팔로우 + async deleteFollow( + userId: number, + followingId: number, + ): Promise { + console.log('언팔로우 서비스 호출'); + const followEntity: UserFollowingEntity = + await UserFollowingEntity.findOneOrFail({ + where: { user: { id: userId }, followUser: { id: followingId } }, + }); + + try { + await followEntity.softRemove(); + return followEntity; + } catch (e) { + console.error('언팔로우 요청에 실패하였습니다: '); + throw new Error(e.message); } + } } diff --git a/src/journey/journey.controller.ts b/src/journey/journey.controller.ts index 80aea7e..6ffb133 100644 --- a/src/journey/journey.controller.ts +++ b/src/journey/journey.controller.ts @@ -72,10 +72,7 @@ export class JourneyController { }) @UseGuards(UserGuard) @Delete('delete/:journeyId') - async deleteJourney( - @Param('journeyId') journeyId: number, - @Req() req: Request, - ) { + async deleteJourney(@Param('journeyId') journeyId: number) { const result = await this.journeyService.deleteJourney(journeyId); return result; } diff --git a/src/journey/journey.service.ts b/src/journey/journey.service.ts index b1811f3..715d6f6 100644 --- a/src/journey/journey.service.ts +++ b/src/journey/journey.service.ts @@ -1,9 +1,5 @@ // journey.service.ts -import { - ConflictException, - Injectable, - NotFoundException, -} from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { addDays, isAfter, isEqual } from 'date-fns'; import { JourneyEntity } from './model/journey.entity'; import { errResponse, response } from 'src/response/response'; @@ -34,7 +30,7 @@ export class JourneyService { const startDate = new Date(createJourneyDto.startDate); const endDate = new Date(createJourneyDto.endDate); - const schedules = await this.createSchedules(journey, startDate, endDate); + await this.createSchedules(journey, startDate, endDate); return errResponse(BaseResponse.JOURNEY_CREATED); } @@ -43,7 +39,6 @@ export class JourneyService { startDate: Date, endDate: Date, ) { - let currentDate = startDate; const schedules = []; // startDate와 endDate가 같은 경우 하나의 schedule 생성 @@ -78,10 +73,10 @@ export class JourneyService { return errResponse(BaseResponse.JOURNEY_NOT_FOUND); } if (title === null) { - const updateJourney = await JourneyEntity.updateJourney(journey, ''); + await JourneyEntity.updateJourney(journey, ''); return response(BaseResponse.UPDATE_JOURNEY_TITLE_SUCCESS); } - const updateJourney = await JourneyEntity.updateJourney(journey, title); + await JourneyEntity.updateJourney(journey, title); return response(BaseResponse.UPDATE_JOURNEY_TITLE_SUCCESS); } @@ -96,7 +91,7 @@ export class JourneyService { await this.deleteScheduleRelations(schedule); } - const deleteJourney = await JourneyEntity.deleteJourney(journey); + await JourneyEntity.deleteJourney(journey); return response(BaseResponse.DELETE_JOURNEY_SUCCESS); } async deleteScheduleRelations(schedule) { diff --git a/src/journey/model/journey.entity.ts b/src/journey/model/journey.entity.ts index 1c546fb..1d0217f 100644 --- a/src/journey/model/journey.entity.ts +++ b/src/journey/model/journey.entity.ts @@ -14,11 +14,10 @@ import { LessThanOrEqual, MoreThanOrEqual, } from 'typeorm'; -import { startOfMonth, endOfMonth, isWithinInterval } from 'date-fns'; +import { isWithinInterval } from 'date-fns'; import { ScheduleEntity } from 'src/schedule/schedule.entity'; import { UserEntity } from 'src/user/user.entity'; import { MonthInfoDto } from 'src/map/month-info.dto'; -import { CreateJourneyDto } from '../dtos/create-journey.dto'; @Entity() export class JourneyEntity extends BaseEntity { diff --git a/src/location/location.entity.ts b/src/location/location.entity.ts index 300f9ed..3ff79ca 100644 --- a/src/location/location.entity.ts +++ b/src/location/location.entity.ts @@ -83,11 +83,4 @@ export class LocationEntity extends BaseEntity { }); return location; } - - static async findExistLocationById(schedule) { - const existLocation = await LocationEntity.findOne({ - where: { schedules: {} }, - }); - return existLocation; - } } diff --git a/src/map/map.service.ts b/src/map/map.service.ts index ea4be7d..4cc52c8 100644 --- a/src/map/map.service.ts +++ b/src/map/map.service.ts @@ -6,7 +6,6 @@ import { UserEntity } from 'src/user/user.entity'; import { DiaryEntity } from 'src/diary/models/diary.entity'; import { ScheduleEntity } from 'src/schedule/schedule.entity'; import { MonthInfoDto } from './month-info.dto'; -import { LocationEntity } from 'src/location/location.entity'; import { DiaryImageEntity } from 'src/diary/models/diary.image.entity'; import { DetailScheduleEntity } from 'src/detail-schedule/detail-schedule.entity'; import { CursorBasedPaginationRequestDto } from './cursor-based-pagination-request.dto.ts'; diff --git a/src/mate/cursor-page/cursor-page-option.dto.ts b/src/mate/cursor-page/cursor-page-option.dto.ts index 8319054..821cc11 100644 --- a/src/mate/cursor-page/cursor-page-option.dto.ts +++ b/src/mate/cursor-page/cursor-page-option.dto.ts @@ -1,11 +1,10 @@ // cursor-page.options.dto.ts -import { Type } from "class-transformer"; -import { IsEnum, IsOptional } from "class-validator"; +import { Type } from 'class-transformer'; +import { IsEnum, IsOptional } from 'class-validator'; import { Order } from './cursor-page-order.enum'; export class CursorPageOptionsDto { - @Type(() => String) @IsEnum(Order) @IsOptional() @@ -17,5 +16,5 @@ export class CursorPageOptionsDto { @Type(() => Number) @IsOptional() - readonly cursorId?: number = "" as any; -} \ No newline at end of file + readonly cursorId?: number = '' as any; +} diff --git a/src/mate/cursor-page/cursor-page-options-parameter.interface.ts b/src/mate/cursor-page/cursor-page-options-parameter.interface.ts index 3baa0fd..596de7a 100644 --- a/src/mate/cursor-page/cursor-page-options-parameter.interface.ts +++ b/src/mate/cursor-page/cursor-page-options-parameter.interface.ts @@ -5,4 +5,4 @@ export interface CursorPageMetaDtoParameters { total: number; hasNextData: boolean; cursor: number; -} \ No newline at end of file +} diff --git a/src/mate/cursor-page/cursor-page-order.enum.ts b/src/mate/cursor-page/cursor-page-order.enum.ts index 2ff68ab..47e0e41 100644 --- a/src/mate/cursor-page/cursor-page-order.enum.ts +++ b/src/mate/cursor-page/cursor-page-order.enum.ts @@ -1,5 +1,5 @@ // cursor-page-order.enum.ts export enum Order { - ASC = "asc", - DESC = "desc" -} \ No newline at end of file + ASC = 'asc', + DESC = 'desc', +} diff --git a/src/mate/cursor-page/cursor-page.dto.ts b/src/mate/cursor-page/cursor-page.dto.ts index 33f1dc3..d53b792 100644 --- a/src/mate/cursor-page/cursor-page.dto.ts +++ b/src/mate/cursor-page/cursor-page.dto.ts @@ -1,8 +1,7 @@ -import { IsArray } from "class-validator"; +import { IsArray } from 'class-validator'; import { CursorPageMetaDto } from './cursor-page.meta.dto'; export class CursorPageDto { - @IsArray() readonly data: T[]; @@ -12,4 +11,4 @@ export class CursorPageDto { this.data = data; this.meta = meta; } -} \ No newline at end of file +} diff --git a/src/mate/cursor-page/cursor-page.meta.dto.ts b/src/mate/cursor-page/cursor-page.meta.dto.ts index 041c915..62198fa 100644 --- a/src/mate/cursor-page/cursor-page.meta.dto.ts +++ b/src/mate/cursor-page/cursor-page.meta.dto.ts @@ -3,16 +3,20 @@ import { CursorPageMetaDtoParameters } from './cursor-page-options-parameter.interface'; export class CursorPageMetaDto { - readonly total: number; readonly take: number; readonly hasNextData: boolean; readonly cursor: number; - constructor({cursorPageOptionsDto, total, hasNextData, cursor}: CursorPageMetaDtoParameters) { + constructor({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }: CursorPageMetaDtoParameters) { this.take = cursorPageOptionsDto.take; this.total = total; this.hasNextData = hasNextData; this.cursor = cursor; } -} \ No newline at end of file +} diff --git a/src/mate/dto/mate-profile-response.dto.ts b/src/mate/dto/mate-profile-response.dto.ts index 526600f..ae8b4c6 100644 --- a/src/mate/dto/mate-profile-response.dto.ts +++ b/src/mate/dto/mate-profile-response.dto.ts @@ -1,14 +1,14 @@ // mate-profile-response.dto.ts export class MateProfileResponseDto { - _id : number; + _id: number; image: string; nickname: string; introduction: string; is_followed: boolean; - signatures: number; // 시그니처 개수 - follower: number; // 팔로워 수 - following: number; // 팔로잉 수 - isQuit: boolean; // 탈퇴 여부 -} \ No newline at end of file + signatures: number; // 시그니처 개수 + follower: number; // 팔로워 수 + following: number; // 팔로잉 수 + isQuit: boolean; // 탈퇴 여부 +} diff --git a/src/mate/dto/mate-profile-signature.dto.ts b/src/mate/dto/mate-profile-signature.dto.ts index 36fc858..ae3edd7 100644 --- a/src/mate/dto/mate-profile-signature.dto.ts +++ b/src/mate/dto/mate-profile-signature.dto.ts @@ -1,6 +1,6 @@ // mate-profile-signature.dto.ts -export class MateProfileSignatureDto{ +export class MateProfileSignatureDto { _id: number; image: string; -} \ No newline at end of file +} diff --git a/src/mate/dto/mate-recommend-profile.dto.ts b/src/mate/dto/mate-recommend-profile.dto.ts index 905b116..10297c2 100644 --- a/src/mate/dto/mate-recommend-profile.dto.ts +++ b/src/mate/dto/mate-recommend-profile.dto.ts @@ -2,11 +2,11 @@ import { MateSignatureCoverDto } from './mate-signature-cover.dto'; -export class MateRecommendProfileDto{ +export class MateRecommendProfileDto { _id: number; - mateImage: string; // 유저 사진 - mateName: string; // 유저 별명 - is_followed: boolean; // 팔로우 여부 - introduction: string; // 한 줄 소개 + mateImage: string; // 유저 사진 + mateName: string; // 유저 별명 + is_followed: boolean; // 팔로우 여부 + introduction: string; // 한 줄 소개 signatures: MateSignatureCoverDto[]; -} \ No newline at end of file +} diff --git a/src/mate/dto/mate-signature-cover.dto.ts b/src/mate/dto/mate-signature-cover.dto.ts index 8e0db99..16a93fb 100644 --- a/src/mate/dto/mate-signature-cover.dto.ts +++ b/src/mate/dto/mate-signature-cover.dto.ts @@ -1,8 +1,8 @@ // mate-signature-cover.dto.ts -export class MateSignatureCoverDto{ +export class MateSignatureCoverDto { _id: number; - image: string - title: string + image: string; + title: string; liked: number; -} \ No newline at end of file +} diff --git a/src/mate/dto/mate-with-common-location-response.dto.ts b/src/mate/dto/mate-with-common-location-response.dto.ts index f7f772a..f98e151 100644 --- a/src/mate/dto/mate-with-common-location-response.dto.ts +++ b/src/mate/dto/mate-with-common-location-response.dto.ts @@ -2,8 +2,8 @@ import { MateRecommendProfileDto } from './mate-recommend-profile.dto'; -export class MateWithCommonLocationResponseDto{ +export class MateWithCommonLocationResponseDto { location: string; - userName: string; // #112 로그인한 사용자 닉네임 추가 + userName: string; // #112 로그인한 사용자 닉네임 추가 mateProfiles: MateRecommendProfileDto[]; -} \ No newline at end of file +} diff --git a/src/mate/mate.controller.ts b/src/mate/mate.controller.ts index 26d7f10..e485c4f 100644 --- a/src/mate/mate.controller.ts +++ b/src/mate/mate.controller.ts @@ -6,40 +6,40 @@ import { Request } from 'express'; import { CursorPageOptionsDto } from './cursor-page/cursor-page-option.dto'; import { MateService } from './mate.service'; import { ResponseDto } from '../response/response.dto'; -import { MateRecommendProfileDto } from './dto/mate-recommend-profile.dto'; import { ResponseCode } from '../response/response-code.enum'; import { MateWithCommonLocationResponseDto } from './dto/mate-with-common-location-response.dto'; import { MateProfileResponseDto } from './dto/mate-profile-response.dto'; @Controller('/mate') -export class MateController{ - - constructor(private readonly mateService:MateService) {} - +export class MateController { + constructor(private readonly mateService: MateService) {} @Get('/random') // 메이트 탐색 첫째 줄: 랜덤으로 메이트 추천 @UseGuards(UserGuard) async getRandomMateProfileWithInfiniteCursor( @Req() req: Request, - @Query() cursorPageOptionDto: CursorPageOptionsDto - ){ - try{ - const result = await this.mateService.recommendRandomMateWithInfiniteScroll(cursorPageOptionDto, req.user.id); + @Query() cursorPageOptionDto: CursorPageOptionsDto, + ) { + try { + const result = + await this.mateService.recommendRandomMateWithInfiniteScroll( + cursorPageOptionDto, + req.user.id, + ); return new ResponseDto( ResponseCode.GET_RANDOM_MATE_PROFILE_SUCCESS, true, - "랜덤 메이트 추천 데이터 생성 성공", - result + '랜덤 메이트 추천 데이터 생성 성공', + result, ); - } - catch(e){ + } catch (e) { console.log(e); return new ResponseDto( ResponseCode.GET_RANDOM_MATE_PROFILE_FAIL, false, - "랜덤 메이트 추천 데이터 생성 실패", - null + '랜덤 메이트 추천 데이터 생성 실패', + null, ); } } @@ -49,94 +49,99 @@ export class MateController{ async getMateProfileWithMyFirstLocation( @Req() req: Request, ): Promise> { + try { + const result = await this.mateService.getMateProfileWithMyFirstLocation( + req.user.id, + ); - try{ - const result = await this.mateService.getMateProfileWithMyFirstLocation(req.user.id); - - if(!result){ - return new ResponseDto( - ResponseCode.GET_MATE_WITH_COMMON_LOCATION_SUCCESS, - true, - "공통 메이트가 없거나 내 시그니처가 없습니다.", - null - ) - } + if (!result) { return new ResponseDto( ResponseCode.GET_MATE_WITH_COMMON_LOCATION_SUCCESS, true, - "장소 기반 메이트 추천 리스트 가져오기 성공", - result - ); - - } - catch (e){ - console.log(e); - return new ResponseDto( - ResponseCode.GET_MATE_WITH_COMMON_LOCATION_FAIL, - false, - "장소 기반 메이트 추천 실패", - null + '공통 메이트가 없거나 내 시그니처가 없습니다.', + null, ); } + return new ResponseDto( + ResponseCode.GET_MATE_WITH_COMMON_LOCATION_SUCCESS, + true, + '장소 기반 메이트 추천 리스트 가져오기 성공', + result, + ); + } catch (e) { + console.log(e); + return new ResponseDto( + ResponseCode.GET_MATE_WITH_COMMON_LOCATION_FAIL, + false, + '장소 기반 메이트 추천 실패', + null, + ); + } } @Get(':mateId') @UseGuards(UserGuard) async getUserProfile( @Req() req: Request, - @Param('mateId') mateId: number - ): Promise>{ - try{ - const result = await this.mateService.findProfileWithUserId(req.user.id, mateId); + @Param('mateId') mateId: number, + ): Promise> { + try { + const result = await this.mateService.findProfileWithUserId( + req.user.id, + mateId, + ); - if(!result){ + if (!result) { return new ResponseDto( ResponseCode.GET_USER_PROFILE_FAIL, false, - "유저 프로필 정보 가져오기 실패", - null); - } - else{ + '유저 프로필 정보 가져오기 실패', + null, + ); + } else { return new ResponseDto( ResponseCode.GET_USER_PROFILE_SUCCESS, true, - "유저 프로필 정보 가져오기 성공", - result); + '유저 프로필 정보 가져오기 성공', + result, + ); } - - }catch (error) { - console.log("Error at GetUserProfile: ", error); + } catch (error) { + console.log('Error at GetUserProfile: ', error); return new ResponseDto( ResponseCode.GET_USER_PROFILE_FAIL, false, - "유저 프로필 정보 가져오기 실패", - null); + '유저 프로필 정보 가져오기 실패', + null, + ); } } @Get('/signature/:mateId') async getSignaturesWithInfiniteCursor( @Param('mateId') mateId: number, - @Query() cursorPageOptionDto: CursorPageOptionsDto - ){ - try{ - const result = await this.mateService.getSignaturesWithInfiniteCursor(cursorPageOptionDto, mateId); + @Query() cursorPageOptionDto: CursorPageOptionsDto, + ) { + try { + const result = await this.mateService.getSignaturesWithInfiniteCursor( + cursorPageOptionDto, + mateId, + ); return new ResponseDto( ResponseCode.GET_USER_SIGNATURES_SUCCESS, true, - "메이트의 시그니처 가져오기 성공", - result + '메이트의 시그니처 가져오기 성공', + result, ); - - }catch(error){ - console.log("Err on getUserSignatures: ", error); + } catch (error) { + console.log('Err on getUserSignatures: ', error); return new ResponseDto( ResponseCode.GET_USER_SIGNATURES_FAIL, false, - "메이트의 시그니처 가져오기 실패", - null + '메이트의 시그니처 가져오기 실패', + null, ); } } -} \ No newline at end of file +} diff --git a/src/mate/mate.module.ts b/src/mate/mate.module.ts index be8ad90..068204e 100644 --- a/src/mate/mate.module.ts +++ b/src/mate/mate.module.ts @@ -6,7 +6,7 @@ import { S3UtilService } from '../utils/S3.service'; import { SignatureService } from '../signature/signature.service'; @Module({ - controllers: [MateController], - providers: [MateService, UserService, S3UtilService, SignatureService] + controllers: [MateController], + providers: [MateService, UserService, S3UtilService, SignatureService], }) -export class MateModule{} +export class MateModule {} diff --git a/src/mate/mate.service.ts b/src/mate/mate.service.ts index 68e152a..ee45d4e 100644 --- a/src/mate/mate.service.ts +++ b/src/mate/mate.service.ts @@ -7,58 +7,58 @@ import { CursorPageOptionsDto } from './cursor-page/cursor-page-option.dto'; import { CursorPageDto } from './cursor-page/cursor-page.dto'; import { SignatureEntity } from '../signature/domain/signature.entity'; import { SignatureService } from '../signature/signature.service'; -import { LessThan, Like, MoreThan, Not } from 'typeorm'; +import { LessThan, Like } from 'typeorm'; import { CursorPageMetaDto } from './cursor-page/cursor-page.meta.dto'; import { SignaturePageEntity } from '../signature/domain/signature.page.entity'; import { UserEntity } from '../user/user.entity'; import { MateRecommendProfileDto } from './dto/mate-recommend-profile.dto'; -import { MateController } from './mate.controller'; import { MateSignatureCoverDto } from './dto/mate-signature-cover.dto'; import { MateWithCommonLocationResponseDto } from './dto/mate-with-common-location-response.dto'; import { MateProfileResponseDto } from './dto/mate-profile-response.dto'; - @Injectable() -export class MateService{ +export class MateService { constructor( private readonly userService: UserService, private readonly s3Service: S3UtilService, private readonly signatureService: SignatureService, ) {} - async getMateProfileWithMyFirstLocation(userId: number): Promise { - try{ - - const mateWithCommonLocationResponseDto = new MateWithCommonLocationResponseDto(); + async getMateProfileWithMyFirstLocation( + userId: number, + ): Promise { + try { + const mateWithCommonLocationResponseDto = + new MateWithCommonLocationResponseDto(); // 1. 메이트 탐색의 기준이 될 장소 가져오기 = 사용자의 가장 최신 시그니처의 첫 번째 페이지 장소 const mySignaturePageEntity = await SignaturePageEntity.findOne({ where: { - signature:{ - user:{ + signature: { + user: { id: userId, - isQuit: false // 탈퇴한 사용자 필터링 + isQuit: false, // 탈퇴한 사용자 필터링 }, }, - page: 1 + page: 1, }, order: { - created: 'DESC' // 'created'를 내림차순으로 정렬해서 가장 최근꺼 가져오기 + created: 'DESC', // 'created'를 내림차순으로 정렬해서 가장 최근꺼 가져오기 }, }); - if(!mySignaturePageEntity){ // 로그인한 사용자가 아직 한번도 시그니처를 작성한 적이 없을 경우 + if (!mySignaturePageEntity) { + // 로그인한 사용자가 아직 한번도 시그니처를 작성한 적이 없을 경우 return null; } const longLocation = mySignaturePageEntity.location; - console.log("*longLocation: ",longLocation); - + console.log('*longLocation: ', longLocation); // 2. 쉼표로 구분된 현재 'longLocation'에서 핵심 부분인 마지막 부분을 가져오기 const locationBlocks = longLocation.split(','); - const myLocation = locationBlocks[locationBlocks.length-1].trim(); - console.log("*firstLocation: ", myLocation); + const myLocation = locationBlocks[locationBlocks.length - 1].trim(); + console.log('*firstLocation: ', myLocation); const loginUser = await this.userService.findUserById(userId); mateWithCommonLocationResponseDto.location = myLocation; @@ -67,14 +67,14 @@ export class MateService{ // 3. 이제 내 기준 로케이션이 사용된 모든 페이지 가져오기 const commonLocationSignaturePages = await SignaturePageEntity.find({ where: { location: Like(`%${myLocation}%`) }, - relations: ['signature'] + relations: ['signature'], }); // 4. 3번에서 찾아온 페이지의 시그니처 가져오기 const commonLocationSignatures = []; - for(const page of commonLocationSignaturePages){ + for (const page of commonLocationSignaturePages) { const signature = await SignatureEntity.findOne({ - where: { id: page.signature.id}, + where: { id: page.signature.id }, relations: ['user'], }); commonLocationSignatures.push(signature); @@ -82,85 +82,82 @@ export class MateService{ // 5. 시그니처 작성자 기준으로 분류: 중복된 작성자를 또 찾아오지 않기 위해 const signatureGroups = {}; - for(const signature of commonLocationSignatures){ - if(!signatureGroups[signature.user.id]){ // 새로운 유저일 경우 새 리스트 생성, 시그니처 삽입 + for (const signature of commonLocationSignatures) { + if (!signatureGroups[signature.user.id]) { + // 새로운 유저일 경우 새 리스트 생성, 시그니처 삽입 signatureGroups[signature.user.id] = []; signatureGroups[signature.user.id].push(signature); } } - // 6. 유저 아이디 순회하면서 한명씩 찾아서 메이트 프로필 생성하기 - const mateProfiles : MateRecommendProfileDto[] = []; + const mateProfiles: MateRecommendProfileDto[] = []; - for(const authorUserId of Object.keys(signatureGroups)){ - const authorId:number = Number(authorUserId); + for (const authorUserId of Object.keys(signatureGroups)) { + const authorId = Number(authorUserId); const mate = await this.userService.findUserById(authorId); - if(userId == authorId) continue; // 본인은 제외 - const locationSignature:SignatureEntity = signatureGroups[authorId][0]; - const mateProfile: MateRecommendProfileDto = await this.generateMateProfile(mate, userId, locationSignature); + if (userId == authorId) continue; // 본인은 제외 + const locationSignature: SignatureEntity = signatureGroups[authorId][0]; + const mateProfile: MateRecommendProfileDto = + await this.generateMateProfile(mate, userId, locationSignature); mateProfiles.push(mateProfile); - } mateWithCommonLocationResponseDto.mateProfiles = mateProfiles; return mateWithCommonLocationResponseDto; - - } - catch(error){ - console.log("Err: ", error); + } catch (error) { + console.log('Err: ', error); throw error; } } - async recommendRandomMateWithInfiniteScroll(cursorPageOptionsDto: CursorPageOptionsDto, userId: number) { - - let cursorId: number = 0; + async recommendRandomMateWithInfiniteScroll( + cursorPageOptionsDto: CursorPageOptionsDto, + userId: number, + ) { + let cursorId = 0; // [0] 맨 처음 요청일 경우 랜덤 숫자 생성해서 cursorId에 할당 - if(cursorPageOptionsDto.cursorId == 0){ + if (cursorPageOptionsDto.cursorId == 0) { const newUser = await UserEntity.find({ - where: { isQuit: false }, // 탈퇴 필터링 + where: { isQuit: false }, // 탈퇴 필터링 order: { - id: 'DESC' // id를 내림차순으로 정렬해서 가장 최근에 가입한 유저 가져오기 + id: 'DESC', // id를 내림차순으로 정렬해서 가장 최근에 가입한 유저 가져오기 }, - take: 1 + take: 1, }); const max = newUser[0].id + 1; // 랜덤 숫자 생성의 max 값 - console.log('max id: ',max); + console.log('max id: ', max); - const min = 5; // 랜덤 숫자 생성의 min 값 + const min = 5; // 랜덤 숫자 생성의 min 값 // TODO 사용자 늘어나면 min 값 늘리기 cursorId = Math.floor(Math.random() * (max - min + 1)) + min; console.log('random cursor: ', cursorId); - - } - else { + } else { cursorId = cursorPageOptionsDto.cursorId; } - // [1] 무한 스크롤: take만큼 cursorId보다 id값이 작은 유저들 불러오기 const [mates, total] = await UserEntity.findAndCount({ take: cursorPageOptionsDto.take, where: { id: LessThan(cursorId), - isQuit: false + isQuit: false, }, order: { - id: "DESC" as any, + id: 'DESC' as any, }, }); - console.log("mates: ", mates); + console.log('mates: ', mates); // [2] 가져온 메이트들 프로필 커버 만들기 - const mateProfiles:MateRecommendProfileDto[] = []; + const mateProfiles: MateRecommendProfileDto[] = []; - for(const mate of mates){ - if(userId == mate.id) continue; // 본인은 제외 + for (const mate of mates) { + if (userId == mate.id) continue; // 본인은 제외 const mateProfile = await this.generateMateProfile(mate, userId, null); mateProfiles.push(mateProfile); } @@ -180,14 +177,21 @@ export class MateService{ cursor = lastDataPerScroll.id; } - const cursorPageMetaDto = new CursorPageMetaDto( - { cursorPageOptionsDto, total, hasNextData, cursor }); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); return new CursorPageDto(mateProfiles, cursorPageMetaDto); - } - async generateMateProfile(mate:UserEntity, userId:number, locationSignature:SignatureEntity){ + async generateMateProfile( + mate: UserEntity, + userId: number, + locationSignature: SignatureEntity, + ) { const mateProfile = new MateRecommendProfileDto(); // 1. 메이트의 기본 정보 담기 @@ -197,13 +201,16 @@ export class MateService{ // 2. 로그인한 유저가 메이트를 팔로우하는지 팔로우 여부 체크 const myEntity = await this.userService.findUserById(userId); - mateProfile.is_followed = await this.userService.checkIfFollowing(myEntity, mate.id); + mateProfile.is_followed = await this.userService.checkIfFollowing( + myEntity, + mate.id, + ); // 3. 메이트 프로필 사진 가져오기 - let userProfileImage = await this.userService.getProfileImage(mate.id); - if(!userProfileImage) mateProfile.mateImage = null; - else{ - let userImageKey = userProfileImage.imageKey; + const userProfileImage = await this.userService.getProfileImage(mate.id); + if (!userProfileImage) mateProfile.mateImage = null; + else { + const userImageKey = userProfileImage.imageKey; mateProfile.mateImage = await this.s3Service.getImageUrl(userImageKey); } @@ -212,27 +219,33 @@ export class MateService{ [1] 랜덤 메이트 추천: 가장 최신 시그니처 두 개 [2] 장소 기반 추천: 장소 관련 시그니처 1개, 최신 시그니처 1개 ****************************************************/ - console.log("locationSig: ", locationSignature); + console.log('locationSig: ', locationSignature); let recommendSignatures = []; - if(locationSignature == null){ // [1] 랜덤 추천이면 가장 최신 시그니처 두 개 가져오기 - recommendSignatures = await this.signatureService.getMyRecentSignatures(mate.id, 2); - } - else{ // [2] 장소 기반 추천이면 장소 관련 하나, 최신 시그니처 하나 + if (locationSignature == null) { + // [1] 랜덤 추천이면 가장 최신 시그니처 두 개 가져오기 + recommendSignatures = await this.signatureService.getMyRecentSignatures( + mate.id, + 2, + ); + } else { + // [2] 장소 기반 추천이면 장소 관련 하나, 최신 시그니처 하나 recommendSignatures.push(locationSignature); - console.log("recommendSignatures: ",recommendSignatures); + console.log('recommendSignatures: ', recommendSignatures); // ㄱ. 삽입할 최신 시그니처 후보 두 개 가져오기 (두 개 중에 이미 삽입된 시그니처와 다른 것을 추가할 것임) - const recentSignatures = await this.signatureService.getMyRecentSignatures(mate.id, 2); + const recentSignatures = + await this.signatureService.getMyRecentSignatures(mate.id, 2); // ㄴ. 이미 들어있는 시그니처와 id 비교해서 다르면 삽입 - for(const recentSignature of recentSignatures){ - console.log("recentSignature.id: ",recentSignature.id); - console.log("locationSignature.id: ",locationSignature.id); + for (const recentSignature of recentSignatures) { + console.log('recentSignature.id: ', recentSignature.id); + console.log('locationSignature.id: ', locationSignature.id); - if(recentSignature.id != locationSignature.id) { // 이미 들어있는 시그니처와 다른 경우에만 push - console.log("push! : ", recentSignature.id) + if (recentSignature.id != locationSignature.id) { + // 이미 들어있는 시그니처와 다른 경우에만 push + console.log('push! : ', recentSignature.id); recommendSignatures.push(recentSignature); break; } @@ -241,53 +254,76 @@ export class MateService{ const signatureCovers = []; //TODO 작성자가 작성한 시그니처가 하나일 경우에는 리스트에 하나만 담겨있음 프론트에 알리기 -> 완료 - for(const signature of recommendSignatures) { + for (const signature of recommendSignatures) { const signatureCover: MateSignatureCoverDto = new MateSignatureCoverDto(); - console.log("signature.id: ",signature.id); + console.log('signature.id: ', signature.id); signatureCover._id = signature.id; signatureCover.title = signature.title; - let thumbnailImageKey = await SignaturePageEntity.findThumbnail(signature.id); - signatureCover.image = await this.s3Service.getImageUrl(thumbnailImageKey); - - console.log("signatureCover: ", signatureCover); + const thumbnailImageKey = await SignaturePageEntity.findThumbnail( + signature.id, + ); + signatureCover.image = await this.s3Service.getImageUrl( + thumbnailImageKey, + ); + + console.log('signatureCover: ', signatureCover); signatureCovers.push(signatureCover); } mateProfile.signatures = signatureCovers; return mateProfile; - } - async findProfileWithUserId(loginUserId: number, targetUserId): Promise { // 유저 정보 가져오기 - try{ - const targetUserEntity = await this.userService.findUserById(targetUserId); + async findProfileWithUserId( + loginUserId: number, + targetUserId, + ): Promise { + // 유저 정보 가져오기 + try { + const targetUserEntity = await this.userService.findUserById( + targetUserId, + ); console.log(targetUserEntity); // 타겟 유저 프로필 가져오기 - const mateProfileResponseDto:MateProfileResponseDto = new MateProfileResponseDto(); + const mateProfileResponseDto: MateProfileResponseDto = + new MateProfileResponseDto(); mateProfileResponseDto._id = targetUserEntity.id; mateProfileResponseDto.nickname = targetUserEntity.nickname; mateProfileResponseDto.introduction = targetUserEntity.introduction; mateProfileResponseDto.isQuit = targetUserEntity.isQuit; // 타겟 유저 프로필 이미지 가져오기 - const userProfileImageEntity = await this.userService.getProfileImage(targetUserId); - if(userProfileImageEntity == null) mateProfileResponseDto.image = null; - else{ + const userProfileImageEntity = await this.userService.getProfileImage( + targetUserId, + ); + if (userProfileImageEntity == null) mateProfileResponseDto.image = null; + else { const userProfileImageKey = userProfileImageEntity.imageKey; - mateProfileResponseDto.image = await this.s3Service.getImageUrl(userProfileImageKey); + mateProfileResponseDto.image = await this.s3Service.getImageUrl( + userProfileImageKey, + ); } // 현재 로그인한 유저가 타켓 유저를 팔로우하는지 여부 가져오기 - if(loginUserId == targetUserId){ // 현재 로그인 유저와 타겟 유저가 같다면 is_followed = null + if (loginUserId == targetUserId) { + // 현재 로그인 유저와 타겟 유저가 같다면 is_followed = null mateProfileResponseDto.is_followed = null; - }else{ - const loginUserEntity = await this.userService.findUserById(loginUserId); - mateProfileResponseDto.is_followed = await this.userService.checkIfFollowing( loginUserEntity, targetUserId); + } else { + const loginUserEntity = await this.userService.findUserById( + loginUserId, + ); + mateProfileResponseDto.is_followed = + await this.userService.checkIfFollowing( + loginUserEntity, + targetUserId, + ); } // 팔로잉 수 - const followingList = await this.userService.getFollowingList(targetUserId); + const followingList = await this.userService.getFollowingList( + targetUserId, + ); mateProfileResponseDto.following = followingList.length; // 팔로워 수 @@ -295,89 +331,92 @@ export class MateService{ mateProfileResponseDto.follower = followerList.length; // 시그니처 개수 - mateProfileResponseDto.signatures = await this.signatureService.getSignatureCnt(targetUserId); + mateProfileResponseDto.signatures = + await this.signatureService.getSignatureCnt(targetUserId); return mateProfileResponseDto; - - } - catch(error){ - console.log("Err on findProfileWithId Service: ",error); + } catch (error) { + console.log('Err on findProfileWithId Service: ', error); throw error; } } - async getSignaturesWithInfiniteCursor(cursorPageOptionsDto: CursorPageOptionsDto, mateId: number) { - try{ - - let cursorId: number = 0; - - // 1. 맨 처음 요청일 경우 해당 유저의 시그니처 중 가장 최근 시그니처 id 가져오기 - if(cursorPageOptionsDto.cursorId == 0) { - const recentSignature = await SignatureEntity.findOne({ - where: { user: {id: mateId} }, - order: { - id: 'DESC' // id를 내림차순으로 정렬해서 가장 최근에 작성한 시그니처 - } - }); - - cursorId = recentSignature.id + 1; - - } - else cursorId = cursorPageOptionsDto.cursorId; - - - // 2. 무한 스크롤: take만큼 cursorId보다 id값이 작은 시그니처들 불러오기 - const [ signatureEntities, total] = await SignatureEntity.findAndCount({ - take: cursorPageOptionsDto.take, - where: { - id: cursorId ? LessThan(cursorId) : null, - user: { id: mateId } - }, + async getSignaturesWithInfiniteCursor( + cursorPageOptionsDto: CursorPageOptionsDto, + mateId: number, + ) { + try { + let cursorId = 0; + + // 1. 맨 처음 요청일 경우 해당 유저의 시그니처 중 가장 최근 시그니처 id 가져오기 + if (cursorPageOptionsDto.cursorId == 0) { + const recentSignature = await SignatureEntity.findOne({ + where: { user: { id: mateId } }, order: { - id: "DESC" as any, + id: 'DESC', // id를 내림차순으로 정렬해서 가장 최근에 작성한 시그니처 }, }); + cursorId = recentSignature.id + 1; + } else cursorId = cursorPageOptionsDto.cursorId; - // 3. 가져온 시그니처들로 커버 만들기 - const signatureCoverDtos: MateSignatureCoverDto[] = []; + // 2. 무한 스크롤: take만큼 cursorId보다 id값이 작은 시그니처들 불러오기 + const [signatureEntities, total] = await SignatureEntity.findAndCount({ + take: cursorPageOptionsDto.take, + where: { + id: cursorId ? LessThan(cursorId) : null, + user: { id: mateId }, + }, + order: { + id: 'DESC' as any, + }, + }); - for( const signatureEntity of signatureEntities){ - const signatureCover: MateSignatureCoverDto = new MateSignatureCoverDto(); + // 3. 가져온 시그니처들로 커버 만들기 + const signatureCoverDtos: MateSignatureCoverDto[] = []; - signatureCover._id = signatureEntity.id; - signatureCover.title = signatureEntity.title; - signatureCover.liked = signatureEntity.liked; + for (const signatureEntity of signatureEntities) { + const signatureCover: MateSignatureCoverDto = + new MateSignatureCoverDto(); - // 시그니처 썸네일 가져오기 - const imageKey = await SignaturePageEntity.findThumbnail(signatureEntity.id); - signatureCover.image = await this.s3Service.getImageUrl(imageKey); + signatureCover._id = signatureEntity.id; + signatureCover.title = signatureEntity.title; + signatureCover.liked = signatureEntity.liked; - signatureCoverDtos.push(signatureCover); - } + // 시그니처 썸네일 가져오기 + const imageKey = await SignaturePageEntity.findThumbnail( + signatureEntity.id, + ); + signatureCover.image = await this.s3Service.getImageUrl(imageKey); - // 4. 스크롤 설정 - let hasNextData = true; - let cursor: number; + signatureCoverDtos.push(signatureCover); + } - const takePerScroll = cursorPageOptionsDto.take; - const isLastScroll = total <= takePerScroll; - const lastDataPerScroll = signatureEntities[signatureEntities.length - 1]; + // 4. 스크롤 설정 + let hasNextData = true; + let cursor: number; - if (isLastScroll) { - hasNextData = false; - cursor = null; - } else { - cursor = lastDataPerScroll.id; - } + const takePerScroll = cursorPageOptionsDto.take; + const isLastScroll = total <= takePerScroll; + const lastDataPerScroll = signatureEntities[signatureEntities.length - 1]; - const cursorPageMetaDto = new CursorPageMetaDto( - { cursorPageOptionsDto, total, hasNextData, cursor }); + if (isLastScroll) { + hasNextData = false; + cursor = null; + } else { + cursor = lastDataPerScroll.id; + } - return new CursorPageDto(signatureCoverDtos, cursorPageMetaDto); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); - }catch(error){ - throw error; - } + return new CursorPageDto(signatureCoverDtos, cursorPageMetaDto); + } catch (error) { + throw error; + } } -} \ No newline at end of file +} diff --git a/src/response/response-code.enum.ts b/src/response/response-code.enum.ts index 683dc4a..3cc7a57 100644 --- a/src/response/response-code.enum.ts +++ b/src/response/response-code.enum.ts @@ -1,5 +1,3 @@ -import { HttpStatus } from '@nestjs/common'; - export enum ResponseCode { /* 200 OK : 요청 성공 */ SIGNIN_SUCCESS = 'OK', @@ -24,7 +22,6 @@ export enum ResponseCode { GET_NOTIFICATION_COUNT_SUCCESS = 'OK', GET_DIARY_SUCCESS = 'OK', - GET_USER_PROFILE_SUCCESS = 'OK', GET_USER_SIGNATURES_SUCCESS = 'OK', @@ -33,7 +30,6 @@ export enum ResponseCode { FOLLOW_SUCCESS = 'OK', GET_COMMENT_DETAIL_SUCCESS = 'OK', - DELETE_SIGNATURE_SUCCESS = 'OK', PATCH_SIGNATURE_SUCCESS = 'OK', GET_LIKE_SIGNATURE_PROFILES_SUCCESS = 'OK', @@ -43,8 +39,6 @@ export enum ResponseCode { GET_MATE_WITH_COMMON_LOCATION_SUCCESS = 'OK', GET_RANDOM_MATE_PROFILE_SUCCESS = 'OK', - - /* 201 CREATED : 요청 성공, 자원 생성 */ SIGNUP_SUCCESS = 'CREATED', SIGNATURE_CREATED = 'CREATED', @@ -54,9 +48,6 @@ export enum ResponseCode { INVITATION_CREATED = 'CREATED', CREATE_SIGNATURE_COMMENT_SUCCESS = 'CREATED', - - - /* 400 BAD_REQUEST : 잘못된 요청 */ AUTH_NUMBER_INCORRECT = 'BAD_REQUEST', RESET_PASSWORD_FAIL_MATCH = 'BAD_REQUEST', @@ -80,7 +71,6 @@ export enum ResponseCode { DELETE_INVITATION_FAIL = 'BAD_REQUEST', PATCH_RULE_FAIL = 'BAD_REQUEST', - GET_MATE_WITH_COMMON_LOCATION_FAIL = 'BAD_REQUEST', GET_RANDOM_MATE_PROFILE_FAIL = 'BAD_REQUEST', GET_RULE_LIST_FAIL = 'BAD_REQUEST', @@ -89,15 +79,12 @@ export enum ResponseCode { COMMENT_DELETE_FAIL = 'BAD_REQUEST', GET_COMMENT_DETAIL_FAIL = 'BAD_REQUEST', - - SIGNATURE_DELETE_FAIL = 'BAD_REQUEST', SIGNATURE_PATCH_FAIL = 'BAD_REQUEST', GET_LIKE_SIGNATURE_PROFILES_FAIL = 'BAD_REQUEST', GET_SEARCH_MAIN_FAIL = 'BAD_REQUEST', SEARCH_BY_KEYWORD_FAIL = 'BAD_REQUEST', GET_USER_SIGNATURES_FAIL = 'BAD_REQUEST', - /* 401 UNAUTHORIZED : 인증되지 않은 사용자 */ INVALID_AUTH_TOKEN = 'UNAUTHORIZED', diff --git a/src/response/response.dto.ts b/src/response/response.dto.ts index 0045117..49ad25e 100644 --- a/src/response/response.dto.ts +++ b/src/response/response.dto.ts @@ -1,24 +1,32 @@ -import { HttpStatus } from '@nestjs/common'; import { ApiProperty } from '@nestjs/swagger'; -import {ResponseCode} from './response-code.enum'; +import { ResponseCode } from './response-code.enum'; export class ResponseDto { - @ApiProperty({ description: '응답 시간'}) + @ApiProperty({ description: '응답 시간' }) timestamp: Date = new Date(); - @ApiProperty({ description: 'http status code'}) + @ApiProperty({ description: 'http status code' }) code: ResponseCode; @ApiProperty() - success: boolean + success: boolean; - @ApiProperty({ example: '데이터 불러오기 성공', description: '응답 메시지'}) + @ApiProperty({ example: '데이터 불러오기 성공', description: '응답 메시지' }) message: string; - @ApiProperty({ required: false, nullable: true , description: 'Response Body'}) + @ApiProperty({ + required: false, + nullable: true, + description: 'Response Body', + }) data?: T; - public constructor(code: ResponseCode, success:boolean, message: string, data: T) { + public constructor( + code: ResponseCode, + success: boolean, + message: string, + data: T, + ) { this.code = code; this.success = success; this.message = message; diff --git a/src/rule/domain/rule.invitation.entity.ts b/src/rule/domain/rule.invitation.entity.ts index fec931b..63e5036 100644 --- a/src/rule/domain/rule.invitation.entity.ts +++ b/src/rule/domain/rule.invitation.entity.ts @@ -1,26 +1,27 @@ -import { BaseEntity, - Entity, - ManyToOne, - PrimaryGeneratedColumn, +import { + BaseEntity, + Entity, + ManyToOne, + PrimaryGeneratedColumn, JoinColumn, CreateDateColumn, UpdateDateColumn, - DeleteDateColumn, + DeleteDateColumn, } from 'typeorm'; import { UserEntity } from 'src/user/user.entity'; -import { RuleMainEntity } from './rule.main.entity' +import { RuleMainEntity } from './rule.main.entity'; @Entity() export class RuleInvitationEntity extends BaseEntity { @PrimaryGeneratedColumn() id: number; - @ManyToOne(() => RuleMainEntity, ruleMain => ruleMain.invitations) - @JoinColumn({name: 'rule_id'}) + @ManyToOne(() => RuleMainEntity, (ruleMain) => ruleMain.invitations) + @JoinColumn({ name: 'rule_id' }) rule: RuleMainEntity; - @ManyToOne(() => UserEntity, user => user.ruleParticipate) - @JoinColumn({name: 'member_id'}) + @ManyToOne(() => UserEntity, (user) => user.ruleParticipate) + @JoinColumn({ name: 'member_id' }) member: UserEntity; @CreateDateColumn() @@ -32,9 +33,11 @@ export class RuleInvitationEntity extends BaseEntity { @DeleteDateColumn() deleted: Date; - static async findNameById(inviterId: number): Promise<{ memberId : number, name : string }> { - const userEntity : UserEntity = await UserEntity.findOne({ - where: { id: inviterId } + static async findNameById( + inviterId: number, + ): Promise<{ memberId: number; name: string }> { + const userEntity: UserEntity = await UserEntity.findOne({ + where: { id: inviterId }, }); const memberId = inviterId; const name = userEntity.name; @@ -42,11 +45,13 @@ export class RuleInvitationEntity extends BaseEntity { return { memberId, name }; } - static async findInvitationByRuleId(ruleId: number): Promise { + static async findInvitationByRuleId( + ruleId: number, + ): Promise { try { const invitation = await RuleInvitationEntity.find({ - where: {rule: {id : ruleId}}, - relations: {member:true}, + where: { rule: { id: ruleId } }, + relations: { member: true }, }); console.log('invitation 조회 결과 : ', invitation); return invitation; @@ -56,11 +61,13 @@ export class RuleInvitationEntity extends BaseEntity { } } - static async findInvitationByRuleAndUser(ruleId: number, userId: number) : Promise { + static async findInvitationByRuleAndUser( + ruleId: number, + userId: number, + ): Promise { try { const invitation = await RuleInvitationEntity.findOne({ - where: [{rule: {id : ruleId}}, - {member: {id : userId}}] + where: [{ rule: { id: ruleId } }, { member: { id: userId } }], }); console.log('invitation 조회 결과 : ', invitation); return invitation; @@ -71,13 +78,16 @@ export class RuleInvitationEntity extends BaseEntity { } // [member] 멤버인지 확인 - static async isAlreadyMember(ruleId: number, targetUserId: number) :Promise { + static async isAlreadyMember( + ruleId: number, + targetUserId: number, + ): Promise { const isAlreadyMember = await RuleInvitationEntity.findOne({ - where : {member: {id : targetUserId}, rule: {id : ruleId}} - }) + where: { member: { id: targetUserId }, rule: { id: ruleId } }, + }); console.log(isAlreadyMember); if (!!isAlreadyMember) return true; else return false; } -} \ No newline at end of file +} diff --git a/src/rule/domain/rule.main.entity.ts b/src/rule/domain/rule.main.entity.ts index a811548..92f8cf4 100644 --- a/src/rule/domain/rule.main.entity.ts +++ b/src/rule/domain/rule.main.entity.ts @@ -1,14 +1,15 @@ -import { BaseEntity, - Column, - Entity, - PrimaryGeneratedColumn, +import { + BaseEntity, + Column, + Entity, + PrimaryGeneratedColumn, OneToMany, CreateDateColumn, UpdateDateColumn, - DeleteDateColumn, + DeleteDateColumn, } from 'typeorm'; import { RuleSubEntity } from './rule.sub.entity'; -import { RuleInvitationEntity } from './rule.invitation.entity' +import { RuleInvitationEntity } from './rule.invitation.entity'; import { CommentEntity } from 'src/comment/domain/comment.entity'; @Entity() @@ -28,19 +29,22 @@ export class RuleMainEntity extends BaseEntity { @DeleteDateColumn() deleted: Date; - @OneToMany(() => RuleSubEntity, ruleSub => ruleSub.main) + @OneToMany(() => RuleSubEntity, (ruleSub) => ruleSub.main) rules: RuleSubEntity[]; - @OneToMany(() => RuleInvitationEntity, ruleInvitation => ruleInvitation.rule) + @OneToMany( + () => RuleInvitationEntity, + (ruleInvitation) => ruleInvitation.rule, + ) invitations: RuleInvitationEntity[]; - @OneToMany(() => CommentEntity, comment => comment.rule) + @OneToMany(() => CommentEntity, (comment) => comment.rule) comments: CommentEntity[]; static async findMainById(ruleId: number): Promise { - const ruleMain : RuleMainEntity = await RuleMainEntity.findOne({ + const ruleMain: RuleMainEntity = await RuleMainEntity.findOne({ where: { id: ruleId }, - relations: ['rules', 'invitations', 'comments'] + relations: ['rules', 'invitations', 'comments'], }); return ruleMain; @@ -57,4 +61,4 @@ export class RuleMainEntity extends BaseEntity { throw error; } } -} \ No newline at end of file +} diff --git a/src/rule/domain/rule.sub.entity.ts b/src/rule/domain/rule.sub.entity.ts index f1c8849..bdc49cc 100644 --- a/src/rule/domain/rule.sub.entity.ts +++ b/src/rule/domain/rule.sub.entity.ts @@ -1,8 +1,9 @@ -import { BaseEntity, - Column, - Entity, - ManyToOne, - PrimaryGeneratedColumn, +import { + BaseEntity, + Column, + Entity, + ManyToOne, + PrimaryGeneratedColumn, JoinColumn, CreateDateColumn, UpdateDateColumn, @@ -21,8 +22,8 @@ export class RuleSubEntity extends BaseEntity { @Column({ type: 'text' }) ruleDetail: string; - @ManyToOne(() => RuleMainEntity, ruleMain => ruleMain.rules) - @JoinColumn({ name: 'rule_id'}) + @ManyToOne(() => RuleMainEntity, (ruleMain) => ruleMain.rules) + @JoinColumn({ name: 'rule_id' }) main: RuleMainEntity; @CreateDateColumn() @@ -37,7 +38,7 @@ export class RuleSubEntity extends BaseEntity { static async findSubById(ruleId: number): Promise { try { const rule: RuleSubEntity[] = await RuleSubEntity.find({ - where: {main: {id : ruleId}}, + where: { main: { id: ruleId } }, }); return rule; } catch (error) { @@ -45,4 +46,4 @@ export class RuleSubEntity extends BaseEntity { throw error; } } -} \ No newline at end of file +} diff --git a/src/rule/dto/create-rule.dto.ts b/src/rule/dto/create-rule.dto.ts index 80b3592..3d0f299 100644 --- a/src/rule/dto/create-rule.dto.ts +++ b/src/rule/dto/create-rule.dto.ts @@ -1,4 +1,10 @@ -import { IsNotEmpty, IsNumber, IsString, IsArray, ValidateNested } from 'class-validator'; +import { + IsNotEmpty, + IsNumber, + IsString, + IsArray, + ValidateNested, +} from 'class-validator'; import { Type } from 'class-transformer'; class RulePairDto { @IsNotEmpty() diff --git a/src/rule/dto/cursor-page-options-parameter.interface.ts b/src/rule/dto/cursor-page-options-parameter.interface.ts index de61566..403b32e 100644 --- a/src/rule/dto/cursor-page-options-parameter.interface.ts +++ b/src/rule/dto/cursor-page-options-parameter.interface.ts @@ -1,8 +1,8 @@ -import { CursorPageOptionsDto } from "./cursor-page.options.dto"; +import { CursorPageOptionsDto } from './cursor-page.options.dto'; export interface CursorPageMetaDtoParameters { - cursorPageOptionsDto: CursorPageOptionsDto; - total: number; - hasNextData: boolean; - cursor: number; -} \ No newline at end of file + cursorPageOptionsDto: CursorPageOptionsDto; + total: number; + hasNextData: boolean; + cursor: number; +} diff --git a/src/rule/dto/cursor-page-order.enum.ts b/src/rule/dto/cursor-page-order.enum.ts index 0c83c3f..9b0a631 100644 --- a/src/rule/dto/cursor-page-order.enum.ts +++ b/src/rule/dto/cursor-page-order.enum.ts @@ -1,4 +1,4 @@ export enum Order { - ASC = "asc", - DESC = "desc" -} \ No newline at end of file + ASC = 'asc', + DESC = 'desc', +} diff --git a/src/rule/dto/cursor-page.dto.ts b/src/rule/dto/cursor-page.dto.ts index 08c2417..d53b792 100644 --- a/src/rule/dto/cursor-page.dto.ts +++ b/src/rule/dto/cursor-page.dto.ts @@ -1,15 +1,14 @@ -import { IsArray } from "class-validator"; -import { CursorPageMetaDto } from "./cursor-page.meta.dto"; +import { IsArray } from 'class-validator'; +import { CursorPageMetaDto } from './cursor-page.meta.dto'; export class CursorPageDto { + @IsArray() + readonly data: T[]; - @IsArray() - readonly data: T[]; + readonly meta: CursorPageMetaDto; - readonly meta: CursorPageMetaDto; - - constructor(data: T[], meta: CursorPageMetaDto) { - this.data = data; - this.meta = meta; - } -} \ No newline at end of file + constructor(data: T[], meta: CursorPageMetaDto) { + this.data = data; + this.meta = meta; + } +} diff --git a/src/rule/dto/cursor-page.meta.dto.ts b/src/rule/dto/cursor-page.meta.dto.ts index 4fc9fac..a57b55d 100644 --- a/src/rule/dto/cursor-page.meta.dto.ts +++ b/src/rule/dto/cursor-page.meta.dto.ts @@ -1,16 +1,20 @@ -import { CursorPageMetaDtoParameters } from "./cursor-page-options-parameter.interface"; +import { CursorPageMetaDtoParameters } from './cursor-page-options-parameter.interface'; export class CursorPageMetaDto { + readonly total: number; + readonly take: number; + readonly hasNextData: boolean; + readonly cursor: number; - readonly total: number; - readonly take: number; - readonly hasNextData: boolean; - readonly cursor: number; - - constructor({cursorPageOptionsDto, total, hasNextData, cursor}: CursorPageMetaDtoParameters) { - this.take = cursorPageOptionsDto.take; - this.total = total; - this.hasNextData = hasNextData; - this.cursor = cursor; - } -} \ No newline at end of file + constructor({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }: CursorPageMetaDtoParameters) { + this.take = cursorPageOptionsDto.take; + this.total = total; + this.hasNextData = hasNextData; + this.cursor = cursor; + } +} diff --git a/src/rule/dto/cursor-page.options.dto.ts b/src/rule/dto/cursor-page.options.dto.ts index 207fc85..2a71402 100644 --- a/src/rule/dto/cursor-page.options.dto.ts +++ b/src/rule/dto/cursor-page.options.dto.ts @@ -1,19 +1,18 @@ -import { Type } from "class-transformer"; -import { IsEnum, IsOptional } from "class-validator"; -import { Order } from "./cursor-page-order.enum"; +import { Type } from 'class-transformer'; +import { IsEnum, IsOptional } from 'class-validator'; +import { Order } from './cursor-page-order.enum'; export class CursorPageOptionsDto { + @Type(() => String) + @IsEnum(Order) + @IsOptional() + sort?: Order = Order.DESC; - @Type(() => String) - @IsEnum(Order) - @IsOptional() - sort?: Order = Order.DESC; + @Type(() => Number) + @IsOptional() + take?: number = 5; - @Type(() => Number) - @IsOptional() - take?: number = 5; - - @Type(() => Number) - @IsOptional() - cursorId?: number = "" as any; -} \ No newline at end of file + @Type(() => Number) + @IsOptional() + cursorId?: number = '' as any; +} diff --git a/src/rule/dto/detail.rule.dto.ts b/src/rule/dto/detail.rule.dto.ts index c5f0990..6d956ae 100644 --- a/src/rule/dto/detail.rule.dto.ts +++ b/src/rule/dto/detail.rule.dto.ts @@ -1,47 +1,53 @@ -import { IsNotEmpty, IsNumber, IsString, IsArray, ValidateNested } from 'class-validator'; +import { + IsNotEmpty, + IsNumber, + IsString, + IsArray, + ValidateNested, +} from 'class-validator'; import { Type } from 'class-transformer'; export class RulePairDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - ruleTitle: string; + @IsNotEmpty() + @IsString() + ruleTitle: string; - @IsNotEmpty() - @IsString() - ruleDetail: string; + @IsNotEmpty() + @IsString() + ruleDetail: string; } export class DetailMemberDto { - @IsNumber() - id: number; + @IsNumber() + id: number; - @IsString() - name: string; + @IsString() + name: string; - @IsString() - image: string; + @IsString() + image: string; } export class DetailRuleDto { - @IsNotEmpty() - @IsNumber() - id: number; - - @IsNotEmpty() - @IsString() - mainTitle: string; - - @IsArray() - @ValidateNested({each: true}) - @Type(() => RulePairDto) - rulePairs: RulePairDto[]; - - @IsArray() - @ValidateNested({each: true}) - @Type(() => DetailMemberDto) - detailMembers: DetailMemberDto[]; -} \ No newline at end of file + @IsNotEmpty() + @IsNumber() + id: number; + + @IsNotEmpty() + @IsString() + mainTitle: string; + + @IsArray() + @ValidateNested({ each: true }) + @Type(() => RulePairDto) + rulePairs: RulePairDto[]; + + @IsArray() + @ValidateNested({ each: true }) + @Type(() => DetailMemberDto) + detailMembers: DetailMemberDto[]; +} diff --git a/src/rule/dto/get-comment.dto.ts b/src/rule/dto/get-comment.dto.ts index e967cd9..5fdec99 100644 --- a/src/rule/dto/get-comment.dto.ts +++ b/src/rule/dto/get-comment.dto.ts @@ -1,28 +1,34 @@ -import {IsDate, IsNotEmpty, IsNumber, IsOptional, IsString} from 'class-validator'; +import { + IsDate, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; export class GetCommentDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - content: string; + @IsNotEmpty() + @IsString() + content: string; - @IsNotEmpty() - @IsDate() - updated: Date; + @IsNotEmpty() + @IsDate() + updated: Date; - // 탈퇴한 회원이 작성한 댓글도 표시 -> null 허용 - @IsOptional() - @IsNumber() - writerId: number; + // 탈퇴한 회원이 작성한 댓글도 표시 -> null 허용 + @IsOptional() + @IsNumber() + writerId: number; - @IsOptional() - @IsString() - name: string; + @IsOptional() + @IsString() + name: string; - @IsOptional() - @IsString() - image: string; -} \ No newline at end of file + @IsOptional() + @IsString() + image: string; +} diff --git a/src/rule/dto/get-member-list.dto.ts b/src/rule/dto/get-member-list.dto.ts index 964960c..ccd8ccb 100644 --- a/src/rule/dto/get-member-list.dto.ts +++ b/src/rule/dto/get-member-list.dto.ts @@ -1,23 +1,23 @@ import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator'; export class GetMemberListDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - name: string; + @IsNotEmpty() + @IsString() + name: string; - @IsNotEmpty() - @IsString() - email: string; + @IsNotEmpty() + @IsString() + email: string; - @IsOptional() - @IsString() - introduction: string; + @IsOptional() + @IsString() + introduction: string; - @IsOptional() - @IsString() - image: string; -} \ No newline at end of file + @IsOptional() + @IsString() + image: string; +} diff --git a/src/rule/dto/get-rule-list.dto.ts b/src/rule/dto/get-rule-list.dto.ts index 37c6dc7..e59e85d 100644 --- a/src/rule/dto/get-rule-list.dto.ts +++ b/src/rule/dto/get-rule-list.dto.ts @@ -1,38 +1,46 @@ -import {IsArray, IsDate, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested} from 'class-validator'; -import {Type} from "class-transformer"; +import { + IsArray, + IsDate, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, + ValidateNested, +} from 'class-validator'; +import { Type } from 'class-transformer'; export class MemberPairDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - name: string; + @IsNotEmpty() + @IsString() + name: string; - @IsOptional() - @IsString() - image: string; + @IsOptional() + @IsString() + image: string; } export class GetRuleListDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - title: string; + @IsNotEmpty() + @IsString() + title: string; - @IsNotEmpty() - @IsDate() - updated: Date; + @IsNotEmpty() + @IsDate() + updated: Date; - @IsNotEmpty() - @IsNumber() - memberCnt: number; + @IsNotEmpty() + @IsNumber() + memberCnt: number; - @IsArray() - @ValidateNested({ each: true }) - @Type(() => MemberPairDto) - memberPairs: MemberPairDto[]; -} \ No newline at end of file + @IsArray() + @ValidateNested({ each: true }) + @Type(() => MemberPairDto) + memberPairs: MemberPairDto[]; +} diff --git a/src/rule/dto/get-search-member-at-create.dto.ts b/src/rule/dto/get-search-member-at-create.dto.ts index 392ef18..3f78b27 100644 --- a/src/rule/dto/get-search-member-at-create.dto.ts +++ b/src/rule/dto/get-search-member-at-create.dto.ts @@ -1,23 +1,23 @@ -import {IsBoolean, IsNotEmpty, IsNumber, IsOptional, IsString} from 'class-validator'; +import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator'; export class GetSearchMemberAtCreateDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - name: string; + @IsNotEmpty() + @IsString() + name: string; - @IsNotEmpty() - @IsString() - email: string; + @IsNotEmpty() + @IsString() + email: string; - @IsOptional() - @IsString() - introduction: string; + @IsOptional() + @IsString() + introduction: string; - @IsOptional() - @IsString() - image: string; -} \ No newline at end of file + @IsOptional() + @IsString() + image: string; +} diff --git a/src/rule/dto/get-search-member.dto.ts b/src/rule/dto/get-search-member.dto.ts index a6fd99b..ee826b6 100644 --- a/src/rule/dto/get-search-member.dto.ts +++ b/src/rule/dto/get-search-member.dto.ts @@ -1,27 +1,33 @@ -import {IsBoolean, IsNotEmpty, IsNumber, IsOptional, IsString} from 'class-validator'; +import { + IsBoolean, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; export class GetSearchMemberDto { - @IsNotEmpty() - @IsNumber() - id: number; + @IsNotEmpty() + @IsNumber() + id: number; - @IsNotEmpty() - @IsString() - name: string; + @IsNotEmpty() + @IsString() + name: string; - @IsNotEmpty() - @IsString() - email: string; + @IsNotEmpty() + @IsString() + email: string; - @IsOptional() - @IsString() - introduction: string; + @IsOptional() + @IsString() + introduction: string; - @IsOptional() - @IsString() - image: string; + @IsOptional() + @IsString() + image: string; - @IsOptional() - @IsBoolean() - isInvited: boolean; -} \ No newline at end of file + @IsOptional() + @IsBoolean() + isInvited: boolean; +} diff --git a/src/rule/dto/update-rule.dto.ts b/src/rule/dto/update-rule.dto.ts index 7101689..1347f89 100644 --- a/src/rule/dto/update-rule.dto.ts +++ b/src/rule/dto/update-rule.dto.ts @@ -1,35 +1,42 @@ -import {IsNotEmpty, IsNumber, IsString, IsArray, ValidateNested, IsOptional} from 'class-validator'; +import { + IsNotEmpty, + IsNumber, + IsString, + IsArray, + ValidateNested, + IsOptional, +} from 'class-validator'; import { Type } from 'class-transformer'; export class UpdateRulePairDto { - @IsOptional() - @IsNumber() - id: number; + @IsOptional() + @IsNumber() + id: number; - @IsNotEmpty() - @IsNumber() - ruleNumber: number; + @IsNotEmpty() + @IsNumber() + ruleNumber: number; - @IsNotEmpty() - @IsString() - ruleTitle: string; + @IsNotEmpty() + @IsString() + ruleTitle: string; - @IsNotEmpty() - @IsString() - ruleDetail: string; + @IsNotEmpty() + @IsString() + ruleDetail: string; } export class UpdateRuleDto { - @IsNotEmpty() - @IsString() - mainTitle: string; + @IsNotEmpty() + @IsString() + mainTitle: string; - @IsArray() - @ValidateNested({ each: true }) - @Type(() => UpdateRulePairDto) - rulePairs: UpdateRulePairDto[]; + @IsArray() + @ValidateNested({ each: true }) + @Type(() => UpdateRulePairDto) + rulePairs: UpdateRulePairDto[]; - @IsArray() - @IsNumber({}, { each: true }) - membersId: number[]; -} \ No newline at end of file + @IsArray() + @IsNumber({}, { each: true }) + membersId: number[]; +} diff --git a/src/rule/rule.controller.ts b/src/rule/rule.controller.ts index e288269..cbd83fb 100644 --- a/src/rule/rule.controller.ts +++ b/src/rule/rule.controller.ts @@ -1,44 +1,58 @@ -import {Controller, Post, Body, Get, Param, Delete, UseGuards, Req, Query, Patch} from '@nestjs/common'; +import { + Controller, + Post, + Body, + Get, + Param, + Delete, + UseGuards, + Req, + Query, + Patch, +} from '@nestjs/common'; import { RuleService } from './rule.service'; import { CreateRuleDto } from './dto/create-rule.dto'; import { ResponseCode } from '../response/response-code.enum'; import { ResponseDto } from '../response/response.dto'; import { UserGuard } from '../user/user.guard'; import { Request } from 'express'; -import {GetSearchMemberDto} from "./dto/get-search-member.dto"; -import { UpdateRuleDto } from "./dto/update-rule.dto"; -import {CursorPageOptionsDto} from "./dto/cursor-page.options.dto"; -import {CursorPageDto} from "./dto/cursor-page.dto"; -import {GetSearchMemberAtCreateDto} from "./dto/get-search-member-at-create.dto"; +import { GetSearchMemberDto } from './dto/get-search-member.dto'; +import { UpdateRuleDto } from './dto/update-rule.dto'; +import { CursorPageOptionsDto } from './dto/cursor-page.options.dto'; +import { CursorPageDto } from './dto/cursor-page.dto'; +import { GetSearchMemberAtCreateDto } from './dto/get-search-member-at-create.dto'; @Controller('mate/rule') export class RuleController { - constructor( - private readonly ruleService: RuleService, - ) {} + constructor(private readonly ruleService: RuleService) {} // [1] 여행 규칙 상세 페이지 조회 (댓글) - 무한 스크롤 적용 @Get('/detail/comment/:ruleId') @UseGuards(UserGuard) - async getComment(@Req() req: Request, - @Param('ruleId') ruleId: number, - @Query() cursorPageOptionsDto: CursorPageOptionsDto + async getComment( + @Req() req: Request, + @Param('ruleId') ruleId: number, + @Query() cursorPageOptionsDto: CursorPageOptionsDto, ): Promise> { try { - const result = await this.ruleService.getComment(cursorPageOptionsDto, ruleId, req.user.id); + const result = await this.ruleService.getComment( + cursorPageOptionsDto, + ruleId, + req.user.id, + ); return new ResponseDto( - ResponseCode.GET_COMMENT_DETAIL_SUCCESS, - true, - "여행 규칙 상세 페이지 (댓글) 조회 성공", - result + ResponseCode.GET_COMMENT_DETAIL_SUCCESS, + true, + '여행 규칙 상세 페이지 (댓글) 조회 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.GET_COMMENT_DETAIL_FAIL, - false, - e.message, - null + ResponseCode.GET_COMMENT_DETAIL_FAIL, + false, + e.message, + null, ); } } @@ -46,22 +60,27 @@ export class RuleController { // [2] 여행 규칙 멤버 리스트 조회 @Get('/detail/member/:ruleId') @UseGuards(UserGuard) - async getMemberList(@Req() req: Request, - @Param('ruleId') ruleId : number) : Promise> { + async getMemberList( + @Req() req: Request, + @Param('ruleId') ruleId: number, + ): Promise> { try { - const memberList = await this.ruleService.getMemberList(req.user.id, ruleId); + const memberList = await this.ruleService.getMemberList( + req.user.id, + ruleId, + ); return new ResponseDto( - ResponseCode.GET_MEMBER_LIST_SUCCESS, - true, - "여행 규칙 멤버 리스트 불러오기 성공", - memberList + ResponseCode.GET_MEMBER_LIST_SUCCESS, + true, + '여행 규칙 멤버 리스트 불러오기 성공', + memberList, ); } catch (e) { return new ResponseDto( - ResponseCode.GET_MEMBER_LIST_FAIL, - false, - e.message, - null + ResponseCode.GET_MEMBER_LIST_FAIL, + false, + e.message, + null, ); } } @@ -71,23 +90,29 @@ export class RuleController { @Get('/detail/search') @UseGuards(UserGuard) async getSearchMemberAtCreate( - @Query('searchTerm')searchTerm : string, - @Query() cursorPageOptionsDto: CursorPageOptionsDto, - @Req() req: Request): Promise> { + @Query('searchTerm') searchTerm: string, + @Query() cursorPageOptionsDto: CursorPageOptionsDto, + @Req() req: Request, + ): Promise> { try { - const result : CursorPageDto = await this.ruleService.getSearchMemberAtCreate(cursorPageOptionsDto, req.user.id, searchTerm) + const result: CursorPageDto = + await this.ruleService.getSearchMemberAtCreate( + cursorPageOptionsDto, + req.user.id, + searchTerm, + ); return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_SUCCESS, - true, - "초대할 메이트 검색 결과 리스트 불러오기 성공", - result + ResponseCode.GET_SEARCH_RESULT_SUCCESS, + true, + '초대할 메이트 검색 결과 리스트 불러오기 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_FAIL, - false, - e.message, - null + ResponseCode.GET_SEARCH_RESULT_FAIL, + false, + e.message, + null, ); } } @@ -96,24 +121,31 @@ export class RuleController { @Get('/detail/search/:ruleId') @UseGuards(UserGuard) async getSearchMemberAtUpdate( - @Query('searchTerm')searchTerm : string, - @Query() cursorPageOptionsDto: CursorPageOptionsDto, - @Param('ruleId') ruleId: number, - @Req() req: Request): Promise> { + @Query('searchTerm') searchTerm: string, + @Query() cursorPageOptionsDto: CursorPageOptionsDto, + @Param('ruleId') ruleId: number, + @Req() req: Request, + ): Promise> { try { - const result : CursorPageDto = await this.ruleService.getSearchMemberAtUpdate(cursorPageOptionsDto, req.user.id, ruleId, searchTerm) + const result: CursorPageDto = + await this.ruleService.getSearchMemberAtUpdate( + cursorPageOptionsDto, + req.user.id, + ruleId, + searchTerm, + ); return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_SUCCESS, - true, - "초대할 메이트 검색 결과 리스트 불러오기 성공", - result + ResponseCode.GET_SEARCH_RESULT_SUCCESS, + true, + '초대할 메이트 검색 결과 리스트 불러오기 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.GET_SEARCH_RESULT_FAIL, - false, - e.message, - null + ResponseCode.GET_SEARCH_RESULT_FAIL, + false, + e.message, + null, ); } } @@ -121,25 +153,26 @@ export class RuleController { // [4] 여행 규칙 상세 페이지 조회 (게시글) @Get('/detail/:ruleId') @UseGuards(UserGuard) - async getDetail(@Req() req: Request, - @Param('ruleId') ruleId: number): Promise> { - - const result = await this.ruleService.getDetail(req.user.id, ruleId); + async getDetail( + @Req() req: Request, + @Param('ruleId') ruleId: number, + ): Promise> { + await this.ruleService.getDetail(req.user.id, ruleId); try { const result = await this.ruleService.getDetail(req.user.id, ruleId); return new ResponseDto( - ResponseCode.GET_RULE_DETAIL_SUCCESS, - true, - "여행 규칙 상세 페이지 (게시글) 조회 성공", - result + ResponseCode.GET_RULE_DETAIL_SUCCESS, + true, + '여행 규칙 상세 페이지 (게시글) 조회 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.GET_RULE_DETAIL_FAIL, - false, - e.message, - null + ResponseCode.GET_RULE_DETAIL_FAIL, + false, + e.message, + null, ); } } @@ -147,24 +180,29 @@ export class RuleController { // [5] 여행 규칙 수정 @Patch('/detail/:ruleId') @UseGuards(UserGuard) - async updateRule(@Body() updateRuleDto: UpdateRuleDto, - @Req() req: Request, - @Param('ruleId') ruleId: number): Promise> { - + async updateRule( + @Body() updateRuleDto: UpdateRuleDto, + @Req() req: Request, + @Param('ruleId') ruleId: number, + ): Promise> { try { - const result = await this.ruleService.updateRule(updateRuleDto, req.user.id, ruleId); + const result = await this.ruleService.updateRule( + updateRuleDto, + req.user.id, + ruleId, + ); return new ResponseDto( - ResponseCode.PATCH_RULE_SUCCESS, - true, - "여행 규칙 수정 성공", - result + ResponseCode.PATCH_RULE_SUCCESS, + true, + '여행 규칙 수정 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.PATCH_RULE_FAIL, - false, - e.message, - null + ResponseCode.PATCH_RULE_FAIL, + false, + e.message, + null, ); } } @@ -172,22 +210,27 @@ export class RuleController { // [6] 여행 규칙 생성 @Post('/detail') @UseGuards(UserGuard) - async createRule(@Req() req: Request, - @Body() createRuleDto: CreateRuleDto): Promise> { + async createRule( + @Req() req: Request, + @Body() createRuleDto: CreateRuleDto, + ): Promise> { try { - const result = await this.ruleService.createRule(createRuleDto, req.user.id); + const result = await this.ruleService.createRule( + createRuleDto, + req.user.id, + ); return new ResponseDto( - ResponseCode.RULE_CREATED, - true, - "여행 규칙 생성 성공", - result + ResponseCode.RULE_CREATED, + true, + '여행 규칙 생성 성공', + result, ); } catch (e) { return new ResponseDto( - ResponseCode.RULE_CREATION_FAIL, - false, - e.message, - null + ResponseCode.RULE_CREATION_FAIL, + false, + e.message, + null, ); } } @@ -195,22 +238,21 @@ export class RuleController { // [7] 여행 규칙 나가기 @Delete('/:ruleId') @UseGuards(UserGuard) - async deleteInvitation(@Req() req: Request, - @Param('ruleId') ruleId: number){ + async deleteInvitation(@Req() req: Request, @Param('ruleId') ruleId: number) { try { await this.ruleService.deleteInvitation(ruleId, req.user.id); return new ResponseDto( - ResponseCode.DELETE_INVITATION_SUCCESS, - true, - "여행 규칙 나가기 성공", - null + ResponseCode.DELETE_INVITATION_SUCCESS, + true, + '여행 규칙 나가기 성공', + null, ); } catch (e) { return new ResponseDto( - ResponseCode.DELETE_INVITATION_FAIL, - false, - e.message, - null + ResponseCode.DELETE_INVITATION_FAIL, + false, + e.message, + null, ); } } @@ -222,16 +264,18 @@ export class RuleController { try { const result = await this.ruleService.getRuleList(req.user.id); return new ResponseDto( - ResponseCode.GET_RULE_LIST_SUCCESS, - true, - "여행 규칙 전체 리스트 조회 성공", - result); + ResponseCode.GET_RULE_LIST_SUCCESS, + true, + '여행 규칙 전체 리스트 조회 성공', + result, + ); } catch (e) { return new ResponseDto( - ResponseCode.GET_RULE_LIST_FAIL, - false, - e.message, - null); + ResponseCode.GET_RULE_LIST_FAIL, + false, + e.message, + null, + ); } } -} \ No newline at end of file +} diff --git a/src/rule/rule.module.ts b/src/rule/rule.module.ts index b30a405..24c3d93 100644 --- a/src/rule/rule.module.ts +++ b/src/rule/rule.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; import { RuleService } from './rule.service'; import { RuleController } from './rule.controller'; -import { S3UtilService } from "../utils/S3.service"; -import { UserService } from "../user/user.service"; +import { S3UtilService } from '../utils/S3.service'; +import { UserService } from '../user/user.service'; @Module({ controllers: [RuleController], diff --git a/src/rule/rule.service.ts b/src/rule/rule.service.ts index 029fd0d..96d016f 100644 --- a/src/rule/rule.service.ts +++ b/src/rule/rule.service.ts @@ -1,39 +1,47 @@ -import {BadRequestException, Injectable, NotFoundException} from '@nestjs/common'; +import { + BadRequestException, + Injectable, + NotFoundException, +} from '@nestjs/common'; import { CreateRuleDto } from './dto/create-rule.dto'; import { RuleMainEntity } from './domain/rule.main.entity'; import { RuleSubEntity } from './domain/rule.sub.entity'; import { RuleInvitationEntity } from './domain/rule.invitation.entity'; -import { UserEntity} from "../user/user.entity"; -import {DetailMemberDto, DetailRuleDto, RulePairDto} from "./dto/detail.rule.dto"; -import { S3UtilService} from "../utils/S3.service"; -import { GetMemberListDto} from "./dto/get-member-list.dto"; -import {UserService} from "../user/user.service"; -import {GetRuleListDto, MemberPairDto} from "./dto/get-rule-list.dto"; -import {Equal, In, LessThan, Like, MoreThan, Not} from 'typeorm'; -import {GetSearchMemberDto} from "./dto/get-search-member.dto"; -import {UpdateRuleDto} from "./dto/update-rule.dto"; -import {CursorPageOptionsDto} from "./dto/cursor-page.options.dto"; -import {CommentEntity} from "../comment/domain/comment.entity"; -import {GetCommentDto } from "./dto/get-comment.dto"; -import {CursorPageDto} from "./dto/cursor-page.dto"; -import {CursorPageMetaDto} from "./dto/cursor-page.meta.dto"; -import {GetSearchMemberAtCreateDto} from "./dto/get-search-member-at-create.dto"; -import {UserFollowingEntity} from "../user/user.following.entity"; +import { UserEntity } from '../user/user.entity'; +import { + DetailMemberDto, + DetailRuleDto, + RulePairDto, +} from './dto/detail.rule.dto'; +import { S3UtilService } from '../utils/S3.service'; +import { GetMemberListDto } from './dto/get-member-list.dto'; +import { UserService } from '../user/user.service'; +import { GetRuleListDto, MemberPairDto } from './dto/get-rule-list.dto'; +import { Like, MoreThan } from 'typeorm'; +import { GetSearchMemberDto } from './dto/get-search-member.dto'; +import { UpdateRuleDto } from './dto/update-rule.dto'; +import { CursorPageOptionsDto } from './dto/cursor-page.options.dto'; +import { CommentEntity } from '../comment/domain/comment.entity'; +import { GetCommentDto } from './dto/get-comment.dto'; +import { CursorPageDto } from './dto/cursor-page.dto'; +import { CursorPageMetaDto } from './dto/cursor-page.meta.dto'; +import { GetSearchMemberAtCreateDto } from './dto/get-search-member-at-create.dto'; +import { UserFollowingEntity } from '../user/user.following.entity'; @Injectable() export class RuleService { constructor( - private readonly s3Service: S3UtilService, - private readonly userService: UserService, - ) { - } + private readonly s3Service: S3UtilService, + private readonly userService: UserService, + ) {} // [1] 여행 규칙 생성 async createRule(dto: CreateRuleDto, userId: number): Promise { - try { // 사용자 검증 - const inviterEntity = await UserEntity.findOneOrFail({where: {id: userId}}); + const inviterEntity = await UserEntity.findOneOrFail({ + where: { id: userId }, + }); if (!inviterEntity) throw new Error('사용자를 찾을 수 없습니다'); // -1) main 저장 @@ -56,20 +64,28 @@ export class RuleService { } // -3) invitation 저장 - const members = await Promise.all(dto.membersId.map(async (memberId): Promise => { - const ruleInvitationEntity = new RuleInvitationEntity(); - - const userEntity = await UserEntity.findOne({ - where: {id: memberId } - }); - if(!userEntity) throw new NotFoundException('멤버로 초대한 회원을 찾을 수 없습니다'); - if(userEntity.isQuit == true) throw new BadRequestException('탈퇴한 회원은 멤버로 초대할 수 없습니다'); - ruleInvitationEntity.rule = main; - ruleInvitationEntity.member = userEntity; - - await ruleInvitationEntity.save(); - return ruleInvitationEntity; - })); + await Promise.all( + dto.membersId.map(async (memberId): Promise => { + const ruleInvitationEntity = new RuleInvitationEntity(); + + const userEntity = await UserEntity.findOne({ + where: { id: memberId }, + }); + if (!userEntity) + throw new NotFoundException( + '멤버로 초대한 회원을 찾을 수 없습니다', + ); + if (userEntity.isQuit == true) + throw new BadRequestException( + '탈퇴한 회원은 멤버로 초대할 수 없습니다', + ); + ruleInvitationEntity.rule = main; + ruleInvitationEntity.member = userEntity; + + await ruleInvitationEntity.save(); + return ruleInvitationEntity; + }), + ); // -4) 여행 규칙 글 작성자 정보 저장 const writerEntity = new RuleInvitationEntity(); @@ -91,77 +107,86 @@ export class RuleService { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ - where: {id: userId}, + where: { id: userId }, }); if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const ruleMain = await RuleMainEntity.findOne({ - where: {id: ruleId}, - relations: {rules: true, invitations: {member: true}} - }) + where: { id: ruleId }, + relations: { rules: true, invitations: { member: true } }, + }); if (!ruleMain) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자인지 체크 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) + where: { member: { id: userId }, rule: { id: ruleId } }, + }); const subs: RuleSubEntity[] = await RuleSubEntity.find({ - where: {main: {id: ruleId}} - }) - const invitations: RuleInvitationEntity[] = await RuleInvitationEntity.find({ - where: {rule: {id: ruleId}}, - relations: {member: {profileImage: true}} + where: { main: { id: ruleId } }, }); + const invitations: RuleInvitationEntity[] = + await RuleInvitationEntity.find({ + where: { rule: { id: ruleId } }, + relations: { member: { profileImage: true } }, + }); - if(!!invitation) { + if (!!invitation) { // -1) 제목 dto.id = ruleId; dto.mainTitle = ruleMain.mainTitle; console.log('dto.id : ', dto.id); // -2) 규칙 - const rulePairs = await Promise.all(subs.map(async (sub): Promise => { - const rulePair = new RulePairDto(); - rulePair.id = sub.id; - rulePair.ruleTitle = sub.ruleTitle; - rulePair.ruleDetail = sub.ruleDetail; - console.log('rulePair.id', rulePair.id); - - return rulePair; - })); + const rulePairs = await Promise.all( + subs.map(async (sub): Promise => { + const rulePair = new RulePairDto(); + rulePair.id = sub.id; + rulePair.ruleTitle = sub.ruleTitle; + rulePair.ruleDetail = sub.ruleDetail; + console.log('rulePair.id', rulePair.id); + + return rulePair; + }), + ); dto.rulePairs = rulePairs.sort((a, b) => a.id - b.id); // -3) 멤버 정보 - const detailMembers = await Promise.all(invitations.map(async (invitation): Promise => { - const detailMember = new DetailMemberDto; - const memberEntity = invitation.member; - if (memberEntity.isQuit == false) { - detailMember.id = memberEntity.id; - detailMember.name = memberEntity.nickname; - console.log('detailMember.id : ', detailMember.id); - - // 사용자 프로필 이미지 - const image = memberEntity.profileImage; - if (image == null) detailMember.image = null; + const detailMembers = await Promise.all( + invitations.map(async (invitation): Promise => { + const detailMember = new DetailMemberDto(); + const memberEntity = invitation.member; + if (memberEntity.isQuit == false) { + detailMember.id = memberEntity.id; + detailMember.name = memberEntity.nickname; + console.log('detailMember.id : ', detailMember.id); + + // 사용자 프로필 이미지 + const image = memberEntity.profileImage; + if (image == null) detailMember.image = null; + else { + const userImageKey = image.imageKey; + detailMember.image = await this.s3Service.getImageUrl( + userImageKey, + ); + } + } + // 탈퇴한 회원인데 ruleInvitationEntity 삭제 안된 경우) else { - const userImageKey = image.imageKey; - detailMember.image = await this.s3Service.getImageUrl(userImageKey); + console.log( + '탈퇴한 회원의 ruleInvitationEntity 가 삭제되지 않았습니다', + ); + console.log('탈퇴한 회원의 ID : ', memberEntity.id); + console.log('해당 ruleInvitationEntity ID : ', invitation.id); + detailMember.id = null; + detailMember.name = null; + detailMember.image = null; } - } - // 탈퇴한 회원인데 ruleInvitationEntity 삭제 안된 경우) - else { - console.log('탈퇴한 회원의 ruleInvitationEntity 가 삭제되지 않았습니다'); - console.log('탈퇴한 회원의 ID : ', memberEntity.id); - console.log('해당 ruleInvitationEntity ID : ', invitation.id); - detailMember.id = null; - detailMember.name = null; - detailMember.image = null; - } - return detailMember; - })); + return detailMember; + }), + ); dto.detailMembers = detailMembers.sort((a, b) => a.id - b.id); return dto; @@ -172,31 +197,34 @@ export class RuleService { console.log('게시글 조회에 실패하였습니다'); throw new Error(e.message); } - }; + } // [3] 여행 규칙 상세 페이지 조회 (댓글) - 페이지네이션 - async getComment(cursorPageOptionsDto: CursorPageOptionsDto, ruleId: number, userId: number): Promise> { - + async getComment( + cursorPageOptionsDto: CursorPageOptionsDto, + ruleId: number, + userId: number, + ): Promise> { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ - where: {id: userId}, + where: { id: userId }, }); if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const ruleMain = await RuleMainEntity.findOne({ - where: {id: ruleId}, + where: { id: ruleId }, }); if (!ruleMain) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자가 아닌 경우 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) + where: { member: { id: userId }, rule: { id: ruleId } }, + }); if (!invitation) throw new Error('사용자가 참여하는 규칙이 아닙니다'); - console.log('--- 검증 완료 ---') + console.log('--- 검증 완료 ---'); // (1) 데이터 조회 const cursorId: number = cursorPageOptionsDto.cursorId; @@ -204,48 +232,52 @@ export class RuleService { const [comments, total] = await CommentEntity.findAndCount({ take: cursorPageOptionsDto.take, where: { - rule: {id: ruleId}, + rule: { id: ruleId }, id: cursorId ? MoreThan(cursorId) : null, }, - relations: {user: {profileImage: true}}, + relations: { user: { profileImage: true } }, order: { - id: "ASC" as any, + id: 'ASC' as any, }, }); - const result = await Promise.all(comments.map(async (comment) => { - const getCommentDto = new GetCommentDto(); + const result = await Promise.all( + comments.map(async (comment) => { + const getCommentDto = new GetCommentDto(); - getCommentDto.id = comment.id; - getCommentDto.content = comment.content; - getCommentDto.updated = comment.updated; + getCommentDto.id = comment.id; + getCommentDto.content = comment.content; + getCommentDto.updated = comment.updated; - // 댓글 작성자 정보 - // 탈퇴한 사용자가 작성한 댓글도 표시 - // -> 댓글 작성자 (user) 존재 여부 확인 - const writerEntity = comment.user; - if (writerEntity.isQuit == false) { - getCommentDto.writerId = comment.user.id; - getCommentDto.name = comment.user.nickname; + // 댓글 작성자 정보 + // 탈퇴한 사용자가 작성한 댓글도 표시 + // -> 댓글 작성자 (user) 존재 여부 확인 + const writerEntity = comment.user; + if (writerEntity.isQuit == false) { + getCommentDto.writerId = comment.user.id; + getCommentDto.name = comment.user.nickname; - // 사용자 프로필 이미지 - const image = comment.user.profileImage; - if (image == null) getCommentDto.image = null; + // 사용자 프로필 이미지 + const image = comment.user.profileImage; + if (image == null) getCommentDto.image = null; + else { + const userImageKey = image.imageKey; + getCommentDto.image = await this.s3Service.getImageUrl( + userImageKey, + ); + } + } + // 댓글 작성자가 탈퇴한 사용자인 경우 else { - const userImageKey = image.imageKey; - getCommentDto.image = await this.s3Service.getImageUrl(userImageKey); + console.log('탈퇴한 회원이 작성한 댓글 입니다'); + getCommentDto.writerId = null; + getCommentDto.name = null; + getCommentDto.image = null; } - } - // 댓글 작성자가 탈퇴한 사용자인 경우 - else { - console.log('탈퇴한 회원이 작성한 댓글 입니다'); - getCommentDto.writerId = null; - getCommentDto.name = null; - getCommentDto.image = null; - } - return getCommentDto; - })); + return getCommentDto; + }), + ); // (2) 페이징 및 정렬 기준 설정 let hasNextData = true; @@ -262,7 +294,12 @@ export class RuleService { cursor = lastDataPerScroll.id; } - const cursorPageMetaDto = new CursorPageMetaDto({cursorPageOptionsDto, total, hasNextData, cursor}); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); return new CursorPageDto(result, cursorPageMetaDto); } catch (e) { @@ -271,24 +308,27 @@ export class RuleService { } // [4] 여행 규칙 나가기 - async deleteInvitation(ruleId: number, userId: number): Promise { + async deleteInvitation( + ruleId: number, + userId: number, + ): Promise { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ - where: {id: userId}, + where: { id: userId }, }); if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const ruleMain = await RuleMainEntity.findOne({ - where: {id: ruleId}, + where: { id: ruleId }, }); if (!ruleMain) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자가 아닌 경우 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) + where: { member: { id: userId }, rule: { id: ruleId } }, + }); if (!!invitation) { return invitation.softRemove(); } else throw new Error('사용자가 참여하는 규칙이 아닙니다'); @@ -299,50 +339,58 @@ export class RuleService { } // [4] 여행 규칙 멤버 리스트 조회 - async getMemberList(userId: number, ruleId: number): Promise { + async getMemberList( + userId: number, + ruleId: number, + ): Promise { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ - where: {id: userId}, + where: { id: userId }, }); if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const ruleMain = await RuleMainEntity.findOne({ - where: {id: ruleId}, + where: { id: ruleId }, }); if (!ruleMain) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자가 아닌 경우 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) - - if(!!invitation) { - const invitationsList: RuleInvitationEntity[] = await RuleInvitationEntity.find({ - where: {rule: {id: ruleId}}, - relations: {member: true} - }); - - const membersList: GetMemberListDto[] = await Promise.all(invitationsList.map(async (invitation): Promise => { - const memberEntity: UserEntity = invitation.member; - const memberDto: GetMemberListDto = new GetMemberListDto(); + where: { member: { id: userId }, rule: { id: ruleId } }, + }); - console.log('memberEntity : ', memberEntity); - memberDto.id = memberEntity.id; - memberDto.name = memberEntity.nickname; - memberDto.email = memberEntity.email; - memberDto.introduction = memberEntity.introduction; + if (!!invitation) { + const invitationsList: RuleInvitationEntity[] = + await RuleInvitationEntity.find({ + where: { rule: { id: ruleId } }, + relations: { member: true }, + }); + + const membersList: GetMemberListDto[] = await Promise.all( + invitationsList.map(async (invitation): Promise => { + const memberEntity: UserEntity = invitation.member; + const memberDto: GetMemberListDto = new GetMemberListDto(); + + console.log('memberEntity : ', memberEntity); + memberDto.id = memberEntity.id; + memberDto.name = memberEntity.nickname; + memberDto.email = memberEntity.email; + memberDto.introduction = memberEntity.introduction; - // 사용자 프로필 이미지 - const image = await this.userService.getProfileImage(memberEntity.id); - if (image == null) memberDto.image = null; - else { - const userImageKey = image.imageKey; - memberDto.image = await this.s3Service.getImageUrl(userImageKey); - } - return memberDto; - })); + // 사용자 프로필 이미지 + const image = await this.userService.getProfileImage( + memberEntity.id, + ); + if (image == null) memberDto.image = null; + else { + const userImageKey = image.imageKey; + memberDto.image = await this.s3Service.getImageUrl(userImageKey); + } + return memberDto; + }), + ); const sortedList = membersList.sort((a, b) => a.id - b.id); return sortedList; } else throw new Error('사용자가 참여하는 규칙이 아닙니다'); @@ -353,7 +401,6 @@ export class RuleService { // [5] 여행 규칙 전체 리스트 조회 async getRuleList(userId: number): Promise { - try { // 검증) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ @@ -376,30 +423,39 @@ export class RuleService { if (!user) throw new Error('사용자를 찾을 수 없습니다'); const invitationEntities = await RuleInvitationEntity.find({ - where: {member: {id: userId}}, + where: { member: { id: userId } }, relations: { rule: { - invitations: true - } - } + invitations: true, + }, + }, }); if (!!invitationEntities) { - const getRuleListDtos = await Promise.all(invitationEntities.map(async (invitation: RuleInvitationEntity): Promise => { - const ruleListDto: GetRuleListDto = new GetRuleListDto; - const ruleId = invitation.rule.id; - const ruleMain = invitation.rule; - - ruleListDto.id = ruleMain.id; - ruleListDto.title = ruleMain.mainTitle; - ruleListDto.updated = ruleMain.updated; - ruleListDto.memberCnt = ruleMain.invitations.length; - ruleListDto.memberPairs = await this.getMemberPairs(ruleId); - - return ruleListDto; - })); + const getRuleListDtos = await Promise.all( + invitationEntities.map( + async ( + invitation: RuleInvitationEntity, + ): Promise => { + const ruleListDto: GetRuleListDto = new GetRuleListDto(); + const ruleId = invitation.rule.id; + const ruleMain = invitation.rule; + + ruleListDto.id = ruleMain.id; + ruleListDto.title = ruleMain.mainTitle; + ruleListDto.updated = ruleMain.updated; + ruleListDto.memberCnt = ruleMain.invitations.length; + ruleListDto.memberPairs = await this.getMemberPairs(ruleId); + + return ruleListDto; + }, + ), + ); - const sortedGetRuleListDtos = getRuleListDtos.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime()); + const sortedGetRuleListDtos = getRuleListDtos.sort( + (a, b) => + new Date(b.updated).getTime() - new Date(a.updated).getTime(), + ); return sortedGetRuleListDtos; } @@ -411,39 +467,44 @@ export class RuleService { async getMemberPairs(ruleId: number): Promise { const invitations = await RuleInvitationEntity.find({ - where: {rule: {id: ruleId}}, + where: { rule: { id: ruleId } }, relations: { member: { - profileImage: true + profileImage: true, + }, + }, + }); + + const result: MemberPairDto[] = await Promise.all( + invitations.map(async (invitation): Promise => { + const memberPair = new MemberPairDto(); + const user: UserEntity = invitation.member; + + console.log('user.id : ', user.id); + memberPair.id = user.id; + memberPair.name = user.nickname; + + // 사용자 프로필 이미지 + const image = user.profileImage; + if (image == null) memberPair.image = null; + else { + const userImageKey = image.imageKey; + memberPair.image = await this.s3Service.getImageUrl(userImageKey); } - } - }) - - const result: MemberPairDto[] = await Promise.all(invitations.map(async (invitation): Promise => { - const memberPair = new MemberPairDto; - const user: UserEntity = invitation.member; - - console.log('user.id : ', user.id); - memberPair.id = user.id; - memberPair.name = user.nickname; - - // 사용자 프로필 이미지 - const image = user.profileImage; - if (image == null) memberPair.image = null; - else { - const userImageKey = image.imageKey; - memberPair.image = await this.s3Service.getImageUrl(userImageKey); - } - return memberPair; - })); + return memberPair; + }), + ); return result; } // [6] 여행 규칙 참여 멤버로 초대할 메이트 검색 결과 - 무한 스크롤 // 여행 규칙 생성 / 여행 규칙 수정 분리 // case1. 여행 규칙 생성 - async getSearchMemberAtCreate(cursorPageOptionsDto: CursorPageOptionsDto, userId: number, searchTerm: string): Promise> { - + async getSearchMemberAtCreate( + cursorPageOptionsDto: CursorPageOptionsDto, + userId: number, + searchTerm: string, + ): Promise> { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ @@ -454,16 +515,16 @@ export class RuleService { if (!user) throw new Error('사용자를 찾을 수 없습니다'); // (1) cursorId 설정 - let cursorId: number = 0; + let cursorId = 0; console.log('cursorPageOptionsDto : ', cursorPageOptionsDto); // -1) 처음 요청인 경우 if (cursorPageOptionsDto.cursorId == 0) { const newUser = await UserEntity.find({ order: { - id: 'DESC' // 가장 최근에 가입한 유저 + id: 'DESC', // 가장 최근에 가입한 유저 }, - take: 1 + take: 1, }); cursorId = newUser[0].id + 1; @@ -472,7 +533,7 @@ export class RuleService { // -2) 처음 요청이 아닌 경우 } else { cursorId = cursorPageOptionsDto.cursorId; - console.log('cursorPageOptionsDto.cursorId != 0 로 인식') + console.log('cursorPageOptionsDto.cursorId != 0 로 인식'); } console.log('cursor: ', cursorId); @@ -493,61 +554,79 @@ export class RuleService { // userFollowingEntity) user: 로그인한 유저, followUser: 유저가 팔로우하는 유저 let resultFollowingEntities = await UserFollowingEntity.find({ where: { - user: {id: userId}, - followUser: {nickname: Like(`%${searchTerm}%`)} + user: { id: userId }, + followUser: { nickname: Like(`%${searchTerm}%`) }, }, relations: { - followUser: { profileImage : true } + followUser: { profileImage: true }, }, order: { - followUser: {id: 'DESC'} - } + followUser: { id: 'DESC' }, + }, }); console.log('resultFollowingEntities', resultFollowingEntities); // 3번 검색 조건) 탈퇴 여부 확인 - resultFollowingEntities = resultFollowingEntities.filter(userFollowingEntity => userFollowingEntity.followUser.isQuit == false); - for(const userFollowingEntity of resultFollowingEntities) { - console.log('isQuit == false : ', userFollowingEntity.followUser.isQuit); + resultFollowingEntities = resultFollowingEntities.filter( + (userFollowingEntity) => userFollowingEntity.followUser.isQuit == false, + ); + for (const userFollowingEntity of resultFollowingEntities) { + console.log( + 'isQuit == false : ', + userFollowingEntity.followUser.isQuit, + ); } const total = resultFollowingEntities.length; // 4번 검색 조건) id 가 cursorId 보다 작은 // 해당 요소보다 작은 요소들만 필터링 - for(const userFollowingEntity of resultFollowingEntities) { - console.log('userFollowingEntity.followUser.id : ', userFollowingEntity.followUser.id); + for (const userFollowingEntity of resultFollowingEntities) { + console.log( + 'userFollowingEntity.followUser.id : ', + userFollowingEntity.followUser.id, + ); } - resultFollowingEntities = resultFollowingEntities.filter(userFollowingEntity => userFollowingEntity.followUser.id < cursorId); + resultFollowingEntities = resultFollowingEntities.filter( + (userFollowingEntity) => userFollowingEntity.followUser.id < cursorId, + ); // take 초기값 설정 console.log('cursorPageOptionsDto.take : ', cursorPageOptionsDto.take); if (cursorPageOptionsDto.take == 0) { cursorPageOptionsDto.take = 5; } - const results = resultFollowingEntities.slice(0, cursorPageOptionsDto.take); + const results = resultFollowingEntities.slice( + 0, + cursorPageOptionsDto.take, + ); console.log('results (UserFollowingEntity[]) : ', results); - const searchResult = await Promise.all(results.map(async (result) => { - const dtoAtCreate: GetSearchMemberAtCreateDto = new GetSearchMemberAtCreateDto(); - const follower = result.followUser; + const searchResult = await Promise.all( + results.map(async (result) => { + const dtoAtCreate: GetSearchMemberAtCreateDto = + new GetSearchMemberAtCreateDto(); + const follower = result.followUser; - dtoAtCreate.id = follower.id; - dtoAtCreate.name = follower.nickname; - dtoAtCreate.email = follower.email; - dtoAtCreate.introduction = follower.introduction; + dtoAtCreate.id = follower.id; + dtoAtCreate.name = follower.nickname; + dtoAtCreate.email = follower.email; + dtoAtCreate.introduction = follower.introduction; - // 사용자 프로필 이미지 - const image = follower.profileImage; - if (image == null) dtoAtCreate.image = null; - else { - const followerImageKey = image.imageKey; - dtoAtCreate.image = await this.s3Service.getImageUrl(followerImageKey); - } - return dtoAtCreate; - })); + // 사용자 프로필 이미지 + const image = follower.profileImage; + if (image == null) dtoAtCreate.image = null; + else { + const followerImageKey = image.imageKey; + dtoAtCreate.image = await this.s3Service.getImageUrl( + followerImageKey, + ); + } + return dtoAtCreate; + }), + ); console.log('searchResult : ', searchResult); @@ -559,7 +638,7 @@ export class RuleService { console.log('takePerScroll : ', takePerScroll); const isLastScroll = total <= takePerScroll; console.log('isLastScroll : ', isLastScroll); - console.log('total : ', total) + console.log('total : ', total); const lastDataPerScroll = searchResult[searchResult.length - 1]; if (isLastScroll) { @@ -569,7 +648,12 @@ export class RuleService { cursor = lastDataPerScroll.id; } - const cursorPageMetaDto = new CursorPageMetaDto({cursorPageOptionsDto, total, hasNextData, cursor}); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); return new CursorPageDto(searchResult, cursorPageMetaDto); } catch (e) { @@ -578,8 +662,12 @@ export class RuleService { } // [6-2] case2. 여행 규칙 수정 - async getSearchMemberAtUpdate(cursorPageOptionsDto: CursorPageOptionsDto, userId: number, ruleId: number, searchTerm: string): Promise> { - + async getSearchMemberAtUpdate( + cursorPageOptionsDto: CursorPageOptionsDto, + userId: number, + ruleId: number, + searchTerm: string, + ): Promise> { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ @@ -590,28 +678,28 @@ export class RuleService { if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const rule = await RuleMainEntity.findOne({ - where: {id: ruleId}, - relations: {rules: true, invitations: {member: true}} - }) + where: { id: ruleId }, + relations: { rules: true, invitations: { member: true } }, + }); if (!rule) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자인지 체크 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) + where: { member: { id: userId }, rule: { id: ruleId } }, + }); - if(!invitation) throw new Error('규칙에 참여하지 않는 사용자 입니다'); + if (!invitation) throw new Error('규칙에 참여하지 않는 사용자 입니다'); // (1) cursorId 설정 - let cursorId: number = 0; + let cursorId = 0; console.log('cursorPageOptionsDto : ', cursorPageOptionsDto); // -1) 처음 요청인 경우 if (cursorPageOptionsDto.cursorId == 0) { const newUser = await UserEntity.find({ order: { - id: 'DESC' // 가장 최근에 가입한 유저 + id: 'DESC', // 가장 최근에 가입한 유저 }, - take: 1 + take: 1, }); cursorId = newUser[0].id + 1; @@ -620,7 +708,7 @@ export class RuleService { // -2) 처음 요청이 아닌 경우 } else { cursorId = cursorPageOptionsDto.cursorId; - console.log('cursorPageOptionsDto.cursorId != 0 로 인식') + console.log('cursorPageOptionsDto.cursorId != 0 로 인식'); } console.log('cursor: ', cursorId); @@ -641,64 +729,82 @@ export class RuleService { // userFollowingEntity) user: 로그인한 유저, followUser: 유저가 팔로우하는 유저 let resultFollowingEntities = await UserFollowingEntity.find({ where: { - user: {id: userId}, - followUser: {nickname: Like(`%${searchTerm}%`)} + user: { id: userId }, + followUser: { nickname: Like(`%${searchTerm}%`) }, }, relations: { - followUser: {profileImage : true, ruleParticipate: {rule: true} } + followUser: { profileImage: true, ruleParticipate: { rule: true } }, }, order: { - followUser: {id: 'DESC'} - } + followUser: { id: 'DESC' }, + }, }); console.log('resultFollowingEntities', resultFollowingEntities); // 3번 검색 조건) 탈퇴 여부 확인 - resultFollowingEntities = resultFollowingEntities.filter(userFollowingEntity => userFollowingEntity.followUser.isQuit == false); - for(const userFollowingEntity of resultFollowingEntities) { - console.log('isQuit == false : ', userFollowingEntity.followUser.isQuit); + resultFollowingEntities = resultFollowingEntities.filter( + (userFollowingEntity) => userFollowingEntity.followUser.isQuit == false, + ); + for (const userFollowingEntity of resultFollowingEntities) { + console.log( + 'isQuit == false : ', + userFollowingEntity.followUser.isQuit, + ); } const total = resultFollowingEntities.length; // 4번 검색 조건) id 가 cursorId 보다 작은 // 해당 요소보다 작은 요소들만 필터링 - for(const userFollowingEntity of resultFollowingEntities) { - console.log('userFollowingEntity.followUser.id : ', userFollowingEntity.followUser.id); + for (const userFollowingEntity of resultFollowingEntities) { + console.log( + 'userFollowingEntity.followUser.id : ', + userFollowingEntity.followUser.id, + ); } - resultFollowingEntities = resultFollowingEntities.filter(userFollowingEntity => userFollowingEntity.followUser.id < cursorId); + resultFollowingEntities = resultFollowingEntities.filter( + (userFollowingEntity) => userFollowingEntity.followUser.id < cursorId, + ); // take 초기값 설정 console.log('cursorPageOptionsDto.take : ', cursorPageOptionsDto.take); if (cursorPageOptionsDto.take == 0) { cursorPageOptionsDto.take = 5; } - const results = resultFollowingEntities.slice(0, cursorPageOptionsDto.take); + const results = resultFollowingEntities.slice( + 0, + cursorPageOptionsDto.take, + ); console.log('results (UserFollowingEntity[]) : ', results); // dto 데이터 넣기 - const searchResult = await Promise.all(results.map(async (result) => { - const dto: GetSearchMemberDto = new GetSearchMemberDto(); - const follower = result.followUser; - - dto.id = follower.id; - dto.name = follower.nickname; - dto.email = follower.email; - dto.introduction = follower.introduction; - // 이미 여행 규칙에 참여하는 멤버인지 여부 - dto.isInvited = await this.userService.checkAlreadyMember(follower.id, ruleId); + const searchResult = await Promise.all( + results.map(async (result) => { + const dto: GetSearchMemberDto = new GetSearchMemberDto(); + const follower = result.followUser; + + dto.id = follower.id; + dto.name = follower.nickname; + dto.email = follower.email; + dto.introduction = follower.introduction; + // 이미 여행 규칙에 참여하는 멤버인지 여부 + dto.isInvited = await this.userService.checkAlreadyMember( + follower.id, + ruleId, + ); - // 사용자 프로필 이미지 - const image = follower.profileImage; - if (image == null) dto.image = null; - else { - const followerImageKey = image.imageKey; - dto.image = await this.s3Service.getImageUrl(followerImageKey); - } - return dto; - })); + // 사용자 프로필 이미지 + const image = follower.profileImage; + if (image == null) dto.image = null; + else { + const followerImageKey = image.imageKey; + dto.image = await this.s3Service.getImageUrl(followerImageKey); + } + return dto; + }), + ); console.log('searchResult : ', searchResult); @@ -717,7 +823,12 @@ export class RuleService { cursor = lastDataPerScroll.id; } - const cursorPageMetaDto = new CursorPageMetaDto({cursorPageOptionsDto, total, hasNextData, cursor}); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); return new CursorPageDto(searchResult, cursorPageMetaDto); } catch (e) { @@ -726,31 +837,34 @@ export class RuleService { } // [7] 여행 규칙 수정 - async updateRule(updateRuleDto: UpdateRuleDto, userId: number, ruleId: number): Promise { - + async updateRule( + updateRuleDto: UpdateRuleDto, + userId: number, + ruleId: number, + ): Promise { try { // 검증1) 사용자가 존재하지 않는 경우 const user = await UserEntity.findOne({ - where: {id: userId}, + where: { id: userId }, }); if (!user) throw new Error('사용자를 찾을 수 없습니다'); // 검증2) 규칙이 존재하지 않는 경우 const rule = await RuleMainEntity.findOne({ - where: {id: ruleId}, - relations: {rules: true, invitations: {member: true}} - }) + where: { id: ruleId }, + relations: { rules: true, invitations: { member: true } }, + }); if (!rule) throw new Error('규칙을 찾을 수 없습니다'); // 검증3) 규칙에 참여하는 사용자인지 체크 const invitation = await RuleInvitationEntity.findOne({ - where: {member: {id: userId}, rule: {id: ruleId}}, - }) + where: { member: { id: userId }, rule: { id: ruleId } }, + }); // -> 규칙에 참여하는 사용자인 경우 if (!!invitation) { updateRuleDto.rulePairs.sort((a, b) => a.ruleNumber - b.ruleNumber); - rule.mainTitle = updateRuleDto.mainTitle + rule.mainTitle = updateRuleDto.mainTitle; await rule.save(); // (1) [상세 규칙 수정] @@ -763,7 +877,7 @@ export class RuleService { // case1) 규칙 삭제 for (const sub of subs) { - let isDeleteSub: boolean = true; + let isDeleteSub = true; for (const updateSub of updateSubsList) { if (sub.id == updateSub.id) { isDeleteSub = false; @@ -780,7 +894,7 @@ export class RuleService { for (const updateSub of updateSubsList) { // case1) 새로운 규칙 if (!updateSub.id) { - const newSub = new RuleSubEntity() + const newSub = new RuleSubEntity(); newSub.main = rule; newSub.ruleTitle = updateSub.ruleTitle; newSub.ruleDetail = updateSub.ruleDetail; @@ -791,8 +905,8 @@ export class RuleService { // case2) 수정 규칙 else { const oldSub = await RuleSubEntity.findOne({ - where: {id: updateSub.id} - }) + where: { id: updateSub.id }, + }); oldSub.ruleTitle = updateSub.ruleTitle; oldSub.ruleDetail = updateSub.ruleDetail; @@ -804,16 +918,16 @@ export class RuleService { // (2) [여행 규칙 멤버 수정] // 기존 멤버 초대 리스트 const oldInvitations = await RuleInvitationEntity.find({ - where: {rule: {id: ruleId}}, - relations: {member: true} - }) + where: { rule: { id: ruleId } }, + relations: { member: true }, + }); // 수정된 멤버 ID 리스트 const updateMemberIds = updateRuleDto.membersId; // case1) 멤버 삭제 for (const invitation of oldInvitations) { const member = invitation.member; - let isDeleteMember: boolean = true; + let isDeleteMember = true; // (예외 상황) 현재 로그인한 사용자 if (member.id == userId) break; @@ -832,9 +946,9 @@ export class RuleService { // case2) 멤버 추가 for (const updateMemberId of updateMemberIds) { - const member = await UserEntity.findExistUser(updateMemberId); + await UserEntity.findExistUser(updateMemberId); - let isPostMember: boolean = true; + let isPostMember = true; for (const oldInvitation of oldInvitations) { const oldMember = oldInvitation.member; @@ -847,20 +961,21 @@ export class RuleService { if (isPostMember) { const newInvitation = new RuleInvitationEntity(); - newInvitation.member = await UserEntity.findExistUser(updateMemberId); + newInvitation.member = await UserEntity.findExistUser( + updateMemberId, + ); newInvitation.rule = rule; await newInvitation.save(); console.log('새로 초대한 멤버 ID : ', updateMemberId); } } - console.log('--여행 규칙 수정이 완료되었습니다--') + console.log('--여행 규칙 수정이 완료되었습니다--'); return rule.id; } else throw new Error('사용자가 참여하는 규칙이 아닙니다'); // -> 여행 규칙에 참여하지 않는 경우 - } catch (e) { console.log('여행 규칙 수정 실패'); throw new Error(e.message); } } -} \ No newline at end of file +} diff --git a/src/schedule/schedule.entity.ts b/src/schedule/schedule.entity.ts index 9c9db63..473d247 100644 --- a/src/schedule/schedule.entity.ts +++ b/src/schedule/schedule.entity.ts @@ -12,7 +12,6 @@ import { Between, } from 'typeorm'; import { NotFoundException } from '@nestjs/common'; -import { startOfMonth, endOfMonth } from 'date-fns'; import { BaseResponse } from 'src/response/response.status'; import { DetailScheduleEntity } from '../detail-schedule/detail-schedule.entity'; import { LocationEntity } from 'src/location/location.entity'; @@ -138,9 +137,6 @@ export class ScheduleEntity extends BaseEntity { return schedules; } - static async findExistScheduleByOptions(journeyId, scheduleId) { - const schedule = await ScheduleEntity.find({}); - } // 월별 일정 조회하기 static async findMonthlySchedule( journeyId, diff --git a/src/schedule/schedule.service.ts b/src/schedule/schedule.service.ts index e078384..454ce80 100644 --- a/src/schedule/schedule.service.ts +++ b/src/schedule/schedule.service.ts @@ -1,11 +1,10 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { response } from 'src/response/response'; import { BaseResponse } from 'src/response/response.status'; import { LocationEntity } from 'src/location/location.entity'; import { ScheduleEntity } from './schedule.entity'; import { UserEntity } from 'src/user/user.entity'; import { UpdateScheduleDto } from './dtos/update-schedule-dto'; -import { JourneyEntity } from 'src/journey/model/journey.entity'; @Injectable() export class ScheduleService { @@ -45,7 +44,7 @@ export class ScheduleService { } async resetSchedule(user, scheduleId) { - const existUser = await UserEntity.findExistUser(user.id); + await UserEntity.findExistUser(user.id); const schedule = await ScheduleEntity.findExistSchedule(scheduleId); // 스케줄이 위치를 가지고 있는지 확인 diff --git a/src/search/dto/get-search-main.dto.ts b/src/search/dto/get-search-main.dto.ts index 07b2da3..9aa5e3e 100644 --- a/src/search/dto/get-search-main.dto.ts +++ b/src/search/dto/get-search-main.dto.ts @@ -2,6 +2,6 @@ import { SignatureCoverDto } from './signature-cover.dto'; -export class GetSearchMainDto{ +export class GetSearchMainDto { covers: SignatureCoverDto[]; -} \ No newline at end of file +} diff --git a/src/search/dto/signature-cover.dto.ts b/src/search/dto/signature-cover.dto.ts index 769e2d4..6112216 100644 --- a/src/search/dto/signature-cover.dto.ts +++ b/src/search/dto/signature-cover.dto.ts @@ -3,9 +3,9 @@ export class SignatureCoverDto { _id: number; title: string; - image: string; // 시그니처 첫 번째 페이지 사진 - userName: string; // 유저 닉네임 - userImage: string; // 유저 프로필 사진 + image: string; // 시그니처 첫 번째 페이지 사진 + userName: string; // 유저 닉네임 + userImage: string; // 유저 프로필 사진 date: string; liked: number; -} \ No newline at end of file +} diff --git a/src/search/search.controller.ts b/src/search/search.controller.ts index f465104..80e5074 100644 --- a/src/search/search.controller.ts +++ b/src/search/search.controller.ts @@ -1,25 +1,22 @@ // search.controller.ts -import { Body, Controller, Get, Query, Req, UseGuards } from '@nestjs/common'; +import { Controller, Get, Query, Req, UseGuards } from '@nestjs/common'; import { ResponseDto } from '../response/response.dto'; import { GetSearchMainDto } from './dto/get-search-main.dto'; import { ResponseCode } from '../response/response-code.enum'; import { SignatureCoverDto } from './dto/signature-cover.dto'; import { SearchService } from './search.service'; -import { UserGuard } from '../user/user.guard'; import { Request } from 'express'; import { OptionalUserGuard } from '../user/optional.user.guard'; @Controller('search') -export class SearchController{ - +export class SearchController { constructor(private readonly searchService: SearchService) {} @Get('/hot') // 팀색탭 메인: 인기 급상승 시그니처 - async getSearchHotSignatures( - ): Promise>{ - try{ - const getHotSignaturesDto:GetSearchMainDto = new GetSearchMainDto(); + async getSearchHotSignatures(): Promise> { + try { + const getHotSignaturesDto: GetSearchMainDto = new GetSearchMainDto(); // 인기 급상승 시그니처 가져오기 getHotSignaturesDto.covers = await this.searchService.findHotSignatures(); @@ -27,16 +24,16 @@ export class SearchController{ return new ResponseDto( ResponseCode.GET_SEARCH_MAIN_SUCCESS, true, - "탐색탭 메인 화면 가져오기 성공", - getHotSignaturesDto + '탐색탭 메인 화면 가져오기 성공', + getHotSignaturesDto, ); - }catch (error){ - console.log("탐색탭 메인 가져오기 실패: ", error); + } catch (error) { + console.log('탐색탭 메인 가져오기 실패: ', error); return new ResponseDto( ResponseCode.GET_SEARCH_MAIN_FAIL, false, - "탐색탭 메인 화면 가져오기 실패", - null + '탐색탭 메인 화면 가져오기 실패', + null, ); } } @@ -45,57 +42,57 @@ export class SearchController{ @UseGuards(OptionalUserGuard) async getSearchNewSignatures( @Req() req?: Request, - ): Promise>{ - try{ - const getMatesNewSignatureDto:GetSearchMainDto = new GetSearchMainDto(); + ): Promise> { + try { + const getMatesNewSignatureDto: GetSearchMainDto = new GetSearchMainDto(); // 로그인 했을 경우 내가 팔로우하는 메이트들의 최신 시그니처 가져오기 - if(req.user != null) getMatesNewSignatureDto.covers = await this.searchService.findMatesNewSignatures(req.user.id); - + if (req.user != null) + getMatesNewSignatureDto.covers = + await this.searchService.findMatesNewSignatures(req.user.id); // 로그인 안했으면 빈 배열 else getMatesNewSignatureDto.covers = null; return new ResponseDto( ResponseCode.GET_SEARCH_MAIN_SUCCESS, true, - "탐색탭 메인 화면 가져오기 성공", - getMatesNewSignatureDto + '탐색탭 메인 화면 가져오기 성공', + getMatesNewSignatureDto, ); - }catch (error){ - console.log("탐색탭 메인 가져오기 실패: ", error); + } catch (error) { + console.log('탐색탭 메인 가져오기 실패: ', error); return new ResponseDto( ResponseCode.GET_SEARCH_MAIN_FAIL, false, - "탐색탭 메인 화면 가져오기 실패", - null + '탐색탭 메인 화면 가져오기 실패', + null, ); } } - @Get('/find') // 탑색탭 검색: 키워드로 시그니처 검색하기 - async search(@Query('keyword') keyword: string): Promise> { - try{ - - const searchResult: SignatureCoverDto[] = await this.searchService.searchByKeyword(keyword); + async search( + @Query('keyword') keyword: string, + ): Promise> { + try { + const searchResult: SignatureCoverDto[] = + await this.searchService.searchByKeyword(keyword); return new ResponseDto( ResponseCode.SEARCH_BY_KEYWORD_SUCCESS, true, - "키워드로 검색하기 성공", - searchResult + '키워드로 검색하기 성공', + searchResult, ); - - }catch(error){ - console.log("탑색- 키워드로 검색 실패: "+error); + } catch (error) { + console.log('탑색- 키워드로 검색 실패: ' + error); return new ResponseDto( ResponseCode.SEARCH_BY_KEYWORD_FAIL, false, - "키워드로 검색하기 실패", - null + '키워드로 검색하기 실패', + null, ); } } - } diff --git a/src/search/search.module.ts b/src/search/search.module.ts index c19bd01..99deb12 100644 --- a/src/search/search.module.ts +++ b/src/search/search.module.ts @@ -8,7 +8,7 @@ import { SignatureService } from '../signature/signature.service'; import { S3UtilService } from '../utils/S3.service'; @Module({ - controllers: [SearchController], - providers: [SearchService, UserService, SignatureService, S3UtilService], + controllers: [SearchController], + providers: [SearchService, UserService, SignatureService, S3UtilService], }) -export class SearchModule {} \ No newline at end of file +export class SearchModule {} diff --git a/src/search/search.service.ts b/src/search/search.service.ts index f61933a..2de42db 100644 --- a/src/search/search.service.ts +++ b/src/search/search.service.ts @@ -5,46 +5,42 @@ import { SignatureEntity } from '../signature/domain/signature.entity'; import { SignatureCoverDto } from './dto/signature-cover.dto'; import { SignaturePageEntity } from '../signature/domain/signature.page.entity'; import { UserService } from '../user/user.service'; -import { exit } from '@nestjs/cli/actions'; -import { SignatureService } from '../signature/signature.service'; import { Like } from 'typeorm'; import { S3UtilService } from '../utils/S3.service'; @Injectable() -export class SearchService{ - +export class SearchService { constructor( private readonly userService: UserService, private readonly s3Service: S3UtilService, ) {} async findHotSignatures(): Promise { - try{ + try { /***************************************** 인기 시그니처 알고리즘 로직: [1] 최근 일주일 안에 올라온 시그니처 모두 가져오기 [2] 그 중에서 좋아요 개수 상위 20개 리턴 *****************************************/ - // [1] 최근 일주일 안에 올라온 시그니처 가져오기 - const recentSignatures: SignatureEntity[] = await SignatureEntity.findRecentSignatures(); + // [1] 최근 일주일 안에 올라온 시그니처 가져오기 + const recentSignatures: SignatureEntity[] = + await SignatureEntity.findRecentSignatures(); // [2] 최근 시그니처들 리스트 좋아요 순으로 정렬 - recentSignatures.sort((a,b) => b.liked - a.liked ); + recentSignatures.sort((a, b) => b.liked - a.liked); console.log(recentSignatures); // [3] 그 중에서 20개만 리턴한다 return await this.getSignatureCoversForSearchMain(recentSignatures); - - }catch(error){ - console.log("Error on findHotSignatures: ", error); + } catch (error) { + console.log('Error on findHotSignatures: ', error); throw error; } - } async findMatesNewSignatures(userId: number) { - try{ + try { /******************************************************** 내 메이트 최신 시그니처 로직: [1] 내가 팔로우하고 있는 메이트 목록 가져오기 @@ -57,68 +53,70 @@ export class SearchService{ // [2] 각 메이트들이 작성한 시그니처 목록에 담기 const totalNewSignatures: SignatureEntity[] = []; - for(const mate of followingMates){ - const mateNewSignatures:SignatureEntity[] = await SignatureEntity.findNewSignaturesByUser(mate.id); + for (const mate of followingMates) { + const mateNewSignatures: SignatureEntity[] = + await SignatureEntity.findNewSignaturesByUser(mate.id); - for(const newSignature of mateNewSignatures){ + for (const newSignature of mateNewSignatures) { totalNewSignatures.push(newSignature); } } // [3] 최신 순으로 정렬 - totalNewSignatures.sort((a, b) => b.created.getTime() - a.created.getTime()); - + totalNewSignatures.sort( + (a, b) => b.created.getTime() - a.created.getTime(), + ); // [4] 20개만 리턴 return await this.getSignatureCoversForSearchMain(totalNewSignatures); - - }catch (error){ - console.log("Error on FindMatesNewSigs: "+error); + } catch (error) { + console.log('Error on FindMatesNewSigs: ' + error); throw error; } } - async getSignatureCoversForSearchMain(signatureEntities){ - + async getSignatureCoversForSearchMain(signatureEntities) { // 탐색 메인화면에 출력될 시그니처 커버 20개 만들기 const signatureCovers: SignatureCoverDto[] = []; for (let i = 0; i < signatureEntities.length && i < 20; i++) { const signature = signatureEntities[i]; const signatureCover = await this.getSignatureCover(signature); - if(signatureCover) signatureCovers.push(signatureCover); + if (signatureCover) signatureCovers.push(signatureCover); } return signatureCovers; } - async searchByKeyword(keyword: string) { // 키워드로 검색하기: 탈퇴한 메이트의 시그니처도 반환 - try{ + async searchByKeyword(keyword: string) { + // 키워드로 검색하기: 탈퇴한 메이트의 시그니처도 반환 + try { const resultSignatures = await SignatureEntity.find({ - where:{ title: Like(`%${keyword}%`) }, - relations: ['user'] // user 포함 + where: { title: Like(`%${keyword}%`) }, + relations: ['user'], // user 포함 }); const resultCovers = []; // 검색 결과 최신 순으로 정렬 - resultSignatures.sort((a, b) => b.created.getTime() - a.created.getTime()); - - for(const signature of resultSignatures){ + resultSignatures.sort( + (a, b) => b.created.getTime() - a.created.getTime(), + ); + + for (const signature of resultSignatures) { const signatureCover = await this.getSignatureCover(signature); - if(signatureCover) resultCovers.push(signatureCover); + if (signatureCover) resultCovers.push(signatureCover); } return resultCovers; - - }catch(error){ - console.log("검색 서비스 에러발생: "+error); + } catch (error) { + console.log('검색 서비스 에러발생: ' + error); throw error; } } - - async getSignatureCover(signature:SignatureEntity) // 시그니처 커버 만들기 - :Promise{ + async getSignatureCover( + signature: SignatureEntity, // 시그니처 커버 만들기 + ): Promise { const signatureCover = new SignatureCoverDto(); signatureCover._id = signature.id; @@ -127,22 +125,30 @@ export class SearchService{ signatureCover.userName = signature.user.nickname; // 시그니처 썸네일 이미지 가져오기 - signatureCover.date = await SignatureEntity.formatDateString(signature.created); - - const signatureImageKey = await SignaturePageEntity.findThumbnail(signature.id); - if(signatureImageKey != null ){ - signatureCover.image = await this.s3Service.getImageUrl(signatureImageKey); - } - else return null; + signatureCover.date = await SignatureEntity.formatDateString( + signature.created, + ); + + const signatureImageKey = await SignaturePageEntity.findThumbnail( + signature.id, + ); + if (signatureImageKey != null) { + signatureCover.image = await this.s3Service.getImageUrl( + signatureImageKey, + ); + } else return null; // 시그니처 작성자 프로필 이미지 가져오기 - const userProfileImageEntity = await this.userService.getProfileImage(signature.user.id); - if(userProfileImageEntity == null) signatureCover.userImage = null; - else{ + const userProfileImageEntity = await this.userService.getProfileImage( + signature.user.id, + ); + if (userProfileImageEntity == null) signatureCover.userImage = null; + else { const userProfileImageKey = userProfileImageEntity.imageKey; - signatureCover.userImage = await this.s3Service.getImageUrl(userProfileImageKey); + signatureCover.userImage = await this.s3Service.getImageUrl( + userProfileImageKey, + ); } return signatureCover; } } - diff --git a/src/signature/domain/signature.comment.entity.ts b/src/signature/domain/signature.comment.entity.ts index 277e0b1..438ef84 100644 --- a/src/signature/domain/signature.comment.entity.ts +++ b/src/signature/domain/signature.comment.entity.ts @@ -1,10 +1,14 @@ // signature.comment.entity.ts import { - BaseEntity, Column, + BaseEntity, + Column, CreateDateColumn, DeleteDateColumn, - Entity, JoinColumn, ManyToOne, OneToMany, + Entity, + JoinColumn, + ManyToOne, + OneToMany, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; @@ -16,23 +20,25 @@ export class SignatureCommentEntity extends BaseEntity { @PrimaryGeneratedColumn() id: number; - @ManyToOne(() => SignatureEntity, - (signature) => signature.comments) + @ManyToOne(() => SignatureEntity, (signature) => signature.comments) @JoinColumn() signature: SignatureEntity; - @ManyToOne(() => UserEntity, - (user) => user.signatureComments) + @ManyToOne(() => UserEntity, (user) => user.signatureComments) @JoinColumn() user: UserEntity; - @OneToMany(() => SignatureCommentEntity, - (childComment) => childComment.parentComment) + @OneToMany( + () => SignatureCommentEntity, + (childComment) => childComment.parentComment, + ) @JoinColumn() childComments: SignatureCommentEntity[]; - @ManyToOne(() => SignatureCommentEntity, - (parentComment) => parentComment.childComments) + @ManyToOne( + () => SignatureCommentEntity, + (parentComment) => parentComment.childComments, + ) @JoinColumn() parentComment: SignatureCommentEntity; @@ -47,4 +53,4 @@ export class SignatureCommentEntity extends BaseEntity { @DeleteDateColumn() deleted: Date; -} \ No newline at end of file +} diff --git a/src/signature/domain/signature.entity.ts b/src/signature/domain/signature.entity.ts index fdf1bc4..7953244 100644 --- a/src/signature/domain/signature.entity.ts +++ b/src/signature/domain/signature.entity.ts @@ -5,20 +5,29 @@ import { Column, CreateDateColumn, DeleteDateColumn, - Entity, EntitySubscriberInterface, EventSubscriber, InsertEvent, JoinColumn, ManyToOne, MoreThan, + Entity, + EntitySubscriberInterface, + EventSubscriber, + InsertEvent, + JoinColumn, + ManyToOne, + MoreThan, OneToMany, - PrimaryGeneratedColumn, RemoveEvent, + PrimaryGeneratedColumn, + RemoveEvent, UpdateDateColumn, } from 'typeorm'; import { UserEntity } from 'src/user/user.entity'; -import { HomeSignatureDto } from '../dto/signature/home-signature.dto'; import { CreateSignatureDto } from '../dto/signature/create-signature.dto'; import { SignaturePageEntity } from './signature.page.entity'; import { SignatureLikeEntity } from './signature.like.entity'; import { SignatureCommentEntity } from './signature.comment.entity'; @Entity() @EventSubscriber() -export class SignatureEntity extends BaseEntity implements EntitySubscriberInterface{ +export class SignatureEntity + extends BaseEntity + implements EntitySubscriberInterface +{ @PrimaryGeneratedColumn() id: number; @@ -28,20 +37,26 @@ export class SignatureEntity extends BaseEntity implements EntitySubscriberInter @Column({ default: 0 }) liked: number; - @ManyToOne(() => UserEntity, - (user) => user.signatures) + @ManyToOne(() => UserEntity, (user) => user.signatures) @JoinColumn({ name: 'user_id' }) user: UserEntity; - @OneToMany(() => SignaturePageEntity, (signaturePage) => signaturePage.signature) + @OneToMany( + () => SignaturePageEntity, + (signaturePage) => signaturePage.signature, + ) signaturePages: SignaturePageEntity[]; - @OneToMany(() => SignatureLikeEntity, - (signatureLike) => signatureLike.signature) + @OneToMany( + () => SignatureLikeEntity, + (signatureLike) => signatureLike.signature, + ) likes: SignatureLikeEntity[]; - @OneToMany(() => SignatureCommentEntity, - (signatureComment) => signatureComment.signature) + @OneToMany( + () => SignatureCommentEntity, + (signatureComment) => signatureComment.signature, + ) comments: SignatureCommentEntity[]; listenTo() { @@ -64,7 +79,6 @@ export class SignatureEntity extends BaseEntity implements EntitySubscriberInter this.save(); // 업데이트된 liked 카운트를 데이터베이스에 저장 } - @CreateDateColumn() created: Date; @@ -83,25 +97,24 @@ export class SignatureEntity extends BaseEntity implements EntitySubscriberInter } static async createSignature( - createSignatureDto: CreateSignatureDto, userId: number + createSignatureDto: CreateSignatureDto, + userId: number, ): Promise { try { const signature: SignatureEntity = new SignatureEntity(); signature.title = createSignatureDto.title; const user: UserEntity = await UserEntity.findOne({ - where: { id: userId} + where: { id: userId }, }); - if(!user){ + if (!user) { throw new Error('User not found'); - } - else{ - console.log("user name: "+ user.name); + } else { + console.log('user name: ' + user.name); signature.user = user; return await signature.save(); - } } catch (error) { console.error('Error creating Signature:', error); @@ -109,31 +122,30 @@ export class SignatureEntity extends BaseEntity implements EntitySubscriberInter } } - - - static async findSignatureById(signatureId: number): Promise { - const signature:SignatureEntity = await SignatureEntity.findOne({ + static async findSignatureById( + signatureId: number, + ): Promise { + const signature: SignatureEntity = await SignatureEntity.findOne({ where: { id: signatureId }, - relations: ['user'] // user 포함 + relations: ['user'], // user 포함 }); return signature; } static async findRecentSignatures(): Promise { - // [1] 기준이 되는 일주일 전 날짜 const sevenDaysAgo: Date = new Date(); - sevenDaysAgo.setDate(sevenDaysAgo.getDate()-7); + sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); console.log(sevenDaysAgo); // [2] 오늘로부터 일주일 안으로 쓰여진 시그니처 가져오기 const recentSignatures = await SignatureEntity.find({ - where:{ + where: { created: MoreThan(sevenDaysAgo), - user: { isQuit: false }, // 탈퇴한 사용자의 시그니처는 추천에서 제외 + user: { isQuit: false }, // 탈퇴한 사용자의 시그니처는 추천에서 제외 }, - relations: ['user'] // user 포함 + relations: ['user'], // user 포함 }); return recentSignatures; @@ -142,14 +154,14 @@ export class SignatureEntity extends BaseEntity implements EntitySubscriberInter static async findNewSignaturesByUser(userId: number) { // [1] 기준이 되는 20일 전 날짜 const twentyDaysAgo: Date = new Date(); - twentyDaysAgo.setDate(twentyDaysAgo.getDate()-20); + twentyDaysAgo.setDate(twentyDaysAgo.getDate() - 20); console.log(twentyDaysAgo); // [2] 20일 전에 쓰인 메이트의 최신 시그니처 가져오기 const signatures = await SignatureEntity.find({ - where:{user:{id: userId}, created: MoreThan(twentyDaysAgo)}, - relations: ['user'] // user 포함 - }) + where: { user: { id: userId }, created: MoreThan(twentyDaysAgo) }, + relations: ['user'], // user 포함 + }); return signatures; } } diff --git a/src/signature/domain/signature.like.entity.ts b/src/signature/domain/signature.like.entity.ts index 0ba8ba3..42a8e0d 100644 --- a/src/signature/domain/signature.like.entity.ts +++ b/src/signature/domain/signature.like.entity.ts @@ -4,7 +4,9 @@ import { BaseEntity, CreateDateColumn, DeleteDateColumn, - Entity, JoinColumn, ManyToOne, + Entity, + JoinColumn, + ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; @@ -16,14 +18,12 @@ export class SignatureLikeEntity extends BaseEntity { @PrimaryGeneratedColumn() id: number; - @ManyToOne(() => SignatureEntity, - (signature) => signature.likes) - @JoinColumn({name: 'signature_id'}) + @ManyToOne(() => SignatureEntity, (signature) => signature.likes) + @JoinColumn({ name: 'signature_id' }) signature: SignatureEntity; - @ManyToOne(() => UserEntity, - (user) => user.likes) - @JoinColumn({name: 'user_id'}) + @ManyToOne(() => UserEntity, (user) => user.likes) + @JoinColumn({ name: 'user_id' }) user: UserEntity; @CreateDateColumn() @@ -36,14 +36,13 @@ export class SignatureLikeEntity extends BaseEntity { deleted: Date; static async createLike(signature: SignatureEntity, loginUser: UserEntity) { - try{ + try { const signatureLike = new SignatureLikeEntity(); signatureLike.signature = signature; signatureLike.user = loginUser; const signatureLikeEntity = await signatureLike.save(); - console.log("sigLike created: ", signatureLikeEntity); - - }catch(error){ + console.log('sigLike created: ', signatureLikeEntity); + } catch (error) { console.error('Error on likeSignature: ', error); throw new Error('Failed to like Signature'); } @@ -51,11 +50,11 @@ export class SignatureLikeEntity extends BaseEntity { static async findSignatureLikes(signatureId: number) { return await SignatureLikeEntity.find({ - where:{ - signature:{id: signatureId}, - user: { isQuit: false } // 탈퇴한 유저의 좋아요는 가져오지 않음 + where: { + signature: { id: signatureId }, + user: { isQuit: false }, // 탈퇴한 유저의 좋아요는 가져오지 않음 }, relations: ['user', 'signature'], - }) + }); } } diff --git a/src/signature/domain/signature.page.entity.ts b/src/signature/domain/signature.page.entity.ts index 7a9183a..fc6321a 100644 --- a/src/signature/domain/signature.page.entity.ts +++ b/src/signature/domain/signature.page.entity.ts @@ -12,7 +12,6 @@ import { UpdateDateColumn, } from 'typeorm'; import { SignatureEntity } from './signature.entity'; -import { PageSignatureDto } from '../dto/signature/page-signature.dto'; @Entity() export class SignaturePageEntity extends BaseEntity { @@ -44,7 +43,6 @@ export class SignaturePageEntity extends BaseEntity { @DeleteDateColumn() deleted: Date; - static async findThumbnail(signatureId: number) { // 각 시그니처의 첫 번째 페이지의 이미지 가져오기 try { @@ -55,14 +53,13 @@ export class SignaturePageEntity extends BaseEntity { }, }); - console.log("첫번째 페이지: ",firstPage); + console.log('첫번째 페이지: ', firstPage); - if(firstPage == null) return null; + if (firstPage == null) return null; else { - console.log("썸네일 이미지: ",firstPage.image); + console.log('썸네일 이미지: ', firstPage.image); return firstPage.image; } - } catch (error) { console.log('Error on findThumbnail: ', error); throw error; diff --git a/src/signature/dto/comment/create-comment.dto.ts b/src/signature/dto/comment/create-comment.dto.ts index 72acced..986074e 100644 --- a/src/signature/dto/comment/create-comment.dto.ts +++ b/src/signature/dto/comment/create-comment.dto.ts @@ -1,6 +1,5 @@ // create-comment.dto.ts -export class CreateCommentDto{ - content: string; // 댓글 내용 - -} \ No newline at end of file +export class CreateCommentDto { + content: string; // 댓글 내용 +} diff --git a/src/signature/dto/comment/get-comment-writer.dto.ts b/src/signature/dto/comment/get-comment-writer.dto.ts index 77d2314..8607d71 100644 --- a/src/signature/dto/comment/get-comment-writer.dto.ts +++ b/src/signature/dto/comment/get-comment-writer.dto.ts @@ -1,8 +1,8 @@ // get-comment-writer.dto.ts -export class GetCommentWriterDto{ +export class GetCommentWriterDto { _id: number; name: string; - image: string; // 프로필 이미지 - is_writer: boolean; // 로그인 유저의 수정 삭제 가능 여부 -} \ No newline at end of file + image: string; // 프로필 이미지 + is_writer: boolean; // 로그인 유저의 수정 삭제 가능 여부 +} diff --git a/src/signature/dto/comment/get-signature-comment.dto.ts b/src/signature/dto/comment/get-signature-comment.dto.ts index af862d3..0949d80 100644 --- a/src/signature/dto/comment/get-signature-comment.dto.ts +++ b/src/signature/dto/comment/get-signature-comment.dto.ts @@ -2,12 +2,12 @@ import { GetCommentWriterDto } from './get-comment-writer.dto'; -export class GetSignatureCommentDto{ +export class GetSignatureCommentDto { _id: number; parentId: number; content: string; writer: GetCommentWriterDto; - date: Date; // 생성 | 수정일 - is_edited: boolean; // 댓글 수정 여부 - can_delete: boolean; // 로그인한 사용자의 댓글 삭제 권한 여부: 시그니처 작성자면 true -} \ No newline at end of file + date: Date; // 생성 | 수정일 + is_edited: boolean; // 댓글 수정 여부 + can_delete: boolean; // 로그인한 사용자의 댓글 삭제 권한 여부: 시그니처 작성자면 true +} diff --git a/src/signature/dto/like/get-like-list.dto.ts b/src/signature/dto/like/get-like-list.dto.ts index e118369..70de855 100644 --- a/src/signature/dto/like/get-like-list.dto.ts +++ b/src/signature/dto/like/get-like-list.dto.ts @@ -2,8 +2,7 @@ import { LikeProfileDto } from './like-profile.dto'; -export class GetLikeListDto{ - liked: number; // 좋아요 개수 +export class GetLikeListDto { + liked: number; // 좋아요 개수 profiles: LikeProfileDto[]; // 좋아요한 사용자 프로필 리스트 - -} \ No newline at end of file +} diff --git a/src/signature/dto/like/like-profile.dto.ts b/src/signature/dto/like/like-profile.dto.ts index ad76feb..409bd99 100644 --- a/src/signature/dto/like/like-profile.dto.ts +++ b/src/signature/dto/like/like-profile.dto.ts @@ -1,9 +1,9 @@ // like-profile.dto.ts -export class LikeProfileDto{ +export class LikeProfileDto { _id: number; nickname: string; introduction: string; is_followed: boolean; image: string; -} \ No newline at end of file +} diff --git a/src/signature/dto/like/like-signature.dto.ts b/src/signature/dto/like/like-signature.dto.ts index 1965a7f..e47d589 100644 --- a/src/signature/dto/like/like-signature.dto.ts +++ b/src/signature/dto/like/like-signature.dto.ts @@ -3,4 +3,4 @@ export class LikeSignatureDto { signatureId: number; liked: number; -} \ No newline at end of file +} diff --git a/src/signature/dto/signature/author-signature.dto.ts b/src/signature/dto/signature/author-signature.dto.ts index 0f1b4f0..5c8f728 100644 --- a/src/signature/dto/signature/author-signature.dto.ts +++ b/src/signature/dto/signature/author-signature.dto.ts @@ -1,8 +1,9 @@ // author-signature.dto.ts -export class AuthorSignatureDto { // 시그니처 작성자 정보 - _id: number; // 메이트 아이디 - name: string; // 메이트 닉네임 - image: string; // 메이트 프로필 이미지 +export class AuthorSignatureDto { + // 시그니처 작성자 정보 + _id: number; // 메이트 아이디 + name: string; // 메이트 닉네임 + image: string; // 메이트 프로필 이미지 is_followed: boolean; // 해당 메이트 팔로우 여부 -} \ No newline at end of file +} diff --git a/src/signature/dto/signature/detail-signature.dto.ts b/src/signature/dto/signature/detail-signature.dto.ts index f58240a..6615f09 100644 --- a/src/signature/dto/signature/detail-signature.dto.ts +++ b/src/signature/dto/signature/detail-signature.dto.ts @@ -2,11 +2,11 @@ import { AuthorSignatureDto } from './author-signature.dto'; import { HeaderSignatureDto } from './header-signature.dto'; -import { PageSignatureDto } from './page-signature.dto'; import { ResponsePageSignatureDto } from './response-page-signature.dto'; -export class DetailSignatureDto { // 시그니처 상세 보기 - author: AuthorSignatureDto; // 시그니처 작성자 정보 - header: HeaderSignatureDto; // 시그니처 제목 및 좋아요 정보 - pages: ResponsePageSignatureDto[]; // 시그니처 각 페이지 내용 -} \ No newline at end of file +export class DetailSignatureDto { + // 시그니처 상세 보기 + author: AuthorSignatureDto; // 시그니처 작성자 정보 + header: HeaderSignatureDto; // 시그니처 제목 및 좋아요 정보 + pages: ResponsePageSignatureDto[]; // 시그니처 각 페이지 내용 +} diff --git a/src/signature/dto/signature/header-signature.dto.ts b/src/signature/dto/signature/header-signature.dto.ts index d320d67..1a4db1d 100644 --- a/src/signature/dto/signature/header-signature.dto.ts +++ b/src/signature/dto/signature/header-signature.dto.ts @@ -1,9 +1,9 @@ // header-signature.dto.ts -export class HeaderSignatureDto{ - _id: number // 시그니처 아이디 - title: string; // 시그니처 제목 - is_liked: boolean; // 해당 시그니처 좋아요 여부 - like_cnt: number; // 좋아요 개수 - date: string; // 발행일 -} \ No newline at end of file +export class HeaderSignatureDto { + _id: number; // 시그니처 아이디 + title: string; // 시그니처 제목 + is_liked: boolean; // 해당 시그니처 좋아요 여부 + like_cnt: number; // 좋아요 개수 + date: string; // 발행일 +} diff --git a/src/signature/dto/signature/home-signature.dto.ts b/src/signature/dto/signature/home-signature.dto.ts index 1dbf511..1cbe72e 100644 --- a/src/signature/dto/signature/home-signature.dto.ts +++ b/src/signature/dto/signature/home-signature.dto.ts @@ -1,8 +1,8 @@ // home-signature.dto.ts export class HomeSignatureDto { - _id: number; // 시그니처 id - title: string; // 시그니처 제목 - date: Date; // 시그니처 발행일 - image: string; // 시그니처 첫번째 페이지의 이미지(썸네일) + _id: number; // 시그니처 id + title: string; // 시그니처 제목 + date: Date; // 시그니처 발행일 + image: string; // 시그니처 첫번째 페이지의 이미지(썸네일) } diff --git a/src/signature/dto/signature/page-signature.dto.ts b/src/signature/dto/signature/page-signature.dto.ts index d1e1aec..f942014 100644 --- a/src/signature/dto/signature/page-signature.dto.ts +++ b/src/signature/dto/signature/page-signature.dto.ts @@ -6,5 +6,5 @@ export class PageSignatureDto { content: string; location: string; //image: Buffer; // form-data 형식 - image: string // base-64 형식 + image: string; // base-64 형식 } diff --git a/src/signature/signature.comment.controller.ts b/src/signature/signature.comment.controller.ts index 651d5ca..4cb368b 100644 --- a/src/signature/signature.comment.controller.ts +++ b/src/signature/signature.comment.controller.ts @@ -2,7 +2,8 @@ import { Body, - Controller, Delete, + Controller, + Delete, ForbiddenException, Get, NotFoundException, @@ -22,166 +23,186 @@ import { ResponseCode } from '../response/response-code.enum'; import { CursorPageOptionsDto } from '../rule/dto/cursor-page.options.dto'; @Controller('signature/:signatureId/comment') -export class SignatureCommentController{ - constructor(private readonly signatureCommentService: SignatureCommentService) {} +export class SignatureCommentController { + constructor( + private readonly signatureCommentService: SignatureCommentService, + ) {} @Post('/') @UseGuards(UserGuard) - async createSignatureComment( // 시그니처 댓글 생성하기 + async createSignatureComment( + // 시그니처 댓글 생성하기 @Req() req: Request, @Param('signatureId') signatureId: number, @Body() newComment: CreateCommentDto, - ){ - try{ - const result = await this.signatureCommentService.createSignatureComment(newComment, req.user.id, signatureId) + ) { + try { + const result = await this.signatureCommentService.createSignatureComment( + newComment, + req.user.id, + signatureId, + ); return new ResponseDto( ResponseCode.CREATE_SIGNATURE_COMMENT_SUCCESS, true, - "시그니처 댓글 생성 성공", - result + '시그니처 댓글 생성 성공', + result, ); - - } - catch(error){ - console.log('Error on createSigComment: ',error); + } catch (error) { + console.log('Error on createSigComment: ', error); return new ResponseDto( ResponseCode.COMMENT_CREATION_FAIL, false, - "시그니처 댓글 생성 실패", - null + '시그니처 댓글 생성 실패', + null, ); } } @Post('/:parentId') @UseGuards(UserGuard) - async createSignatureReplyComment( // 시그니처 답글 생성하기 + async createSignatureReplyComment( + // 시그니처 답글 생성하기 @Req() req: Request, @Param('signatureId') signatureId: number, @Param('parentId') parentId: number, @Body() newComment: CreateCommentDto, - ){ - try{ - const result = await this.signatureCommentService.createSignatureComment(newComment, req.user.id, signatureId, parentId) + ) { + try { + const result = await this.signatureCommentService.createSignatureComment( + newComment, + req.user.id, + signatureId, + parentId, + ); return new ResponseDto( ResponseCode.CREATE_SIGNATURE_COMMENT_SUCCESS, true, - "시그니처 답글 생성 성공", - result + '시그니처 답글 생성 성공', + result, ); - - } - catch(error){ - console.log('Error on createSigComment: ',error); + } catch (error) { + console.log('Error on createSigComment: ', error); return new ResponseDto( ResponseCode.COMMENT_CREATION_FAIL, false, - "시그니처 답글 생성 실패", - null + '시그니처 답글 생성 실패', + null, ); } } @Get('/') @UseGuards(UserGuard) - async getSignatureComment( // 시그니처 댓글 조회하기 (무한 스크롤) + async getSignatureComment( + // 시그니처 댓글 조회하기 (무한 스크롤) @Req() req: Request, @Param('signatureId') signatureId: number, @Query() cursorPageOptionsDto: CursorPageOptionsDto, - ){ - try{ - const result = await this.signatureCommentService.getSignatureComment(cursorPageOptionsDto, req.user.id, signatureId); + ) { + try { + const result = await this.signatureCommentService.getSignatureComment( + cursorPageOptionsDto, + req.user.id, + signatureId, + ); return new ResponseDto( ResponseCode.GET_COMMENT_DETAIL_SUCCESS, true, - "시그니처 댓글 가져오기 성공", - result + '시그니처 댓글 가져오기 성공', + result, ); - } - catch(error){ - console.log('Error on createSigChildComment: ',error); + } catch (error) { + console.log('Error on createSigChildComment: ', error); return new ResponseDto( ResponseCode.GET_COMMENT_DETAIL_FAIL, false, - "시그니처 댓글 가져오기 실패", - null + '시그니처 댓글 가져오기 실패', + null, ); } } @Patch('/:commentId') @UseGuards(UserGuard) - async patchSignatureComment( // 시그니처 수정하기 + async patchSignatureComment( + // 시그니처 수정하기 @Param('signatureId') signatureId: number, @Param('commentId') commentId: number, @Body() patchedComment: CreateCommentDto, @Req() req: Request, - ){ - try{ - const result = await this.signatureCommentService.patchSignatureComment(req.user.id,signatureId,commentId,patchedComment); + ) { + try { + const result = await this.signatureCommentService.patchSignatureComment( + req.user.id, + signatureId, + commentId, + patchedComment, + ); return new ResponseDto( ResponseCode.COMMENT_UPDATE_SUCCESS, true, - "시그니처 댓글 수정하기 성공", - result + '시그니처 댓글 수정하기 성공', + result, ); - } - catch(error){ - console.log("Err on PatchSigComment: "+ error); - let errorMessage = ""; + } catch (error) { + console.log('Err on PatchSigComment: ' + error); + let errorMessage = ''; - if(error instanceof NotFoundException) errorMessage = error.message; - else if(error instanceof ForbiddenException) errorMessage = error.message; - else errorMessage = "시그니처 댓글 수정하기 실패"; + if (error instanceof NotFoundException) errorMessage = error.message; + else if (error instanceof ForbiddenException) + errorMessage = error.message; + else errorMessage = '시그니처 댓글 수정하기 실패'; return new ResponseDto( ResponseCode.COMMENT_UPDATE_FAIL, false, errorMessage, - null + null, ); } } - @Delete('/:commentId') @UseGuards(UserGuard) - async deleteSignatureComment( // 시그니처 수정하기 + async deleteSignatureComment( + // 시그니처 수정하기 @Param('signatureId') signatureId: number, @Param('commentId') commentId: number, @Req() req: Request, - ){ - try{ - const result = await this.signatureCommentService.deleteSignatureComment(req.user.id,signatureId,commentId); + ) { + try { + const result = await this.signatureCommentService.deleteSignatureComment( + req.user.id, + signatureId, + commentId, + ); return new ResponseDto( ResponseCode.COMMENT_DELETE_SUCCESS, true, - "시그니처 댓글 삭제하기 성공", - result + '시그니처 댓글 삭제하기 성공', + result, ); - } - catch(error){ - console.log("Err on DeleteSigComment: "+ error); - let errorMessage = ""; + } catch (error) { + console.log('Err on DeleteSigComment: ' + error); + let errorMessage = ''; - if(error instanceof NotFoundException) errorMessage = error.message; - else if(error instanceof ForbiddenException) errorMessage = error.message; - else errorMessage = "시그니처 댓글 삭제하기 실패"; + if (error instanceof NotFoundException) errorMessage = error.message; + else if (error instanceof ForbiddenException) + errorMessage = error.message; + else errorMessage = '시그니처 댓글 삭제하기 실패'; return new ResponseDto( ResponseCode.COMMENT_DELETE_FAIL, false, errorMessage, - null + null, ); - } } - - -} \ No newline at end of file +} diff --git a/src/signature/signature.comment.service.ts b/src/signature/signature.comment.service.ts index 1fdb89a..9f1b461 100644 --- a/src/signature/signature.comment.service.ts +++ b/src/signature/signature.comment.service.ts @@ -1,6 +1,10 @@ // signature.comment.service.ts -import { ForbiddenException, Injectable, NotFoundException } from '@nestjs/common'; +import { + ForbiddenException, + Injectable, + NotFoundException, +} from '@nestjs/common'; import { UserService } from '../user/user.service'; import { S3UtilService } from '../utils/S3.service'; import { SignatureService } from './signature.service'; @@ -17,31 +21,30 @@ import { CursorPageDto } from '../mate/cursor-page/cursor-page.dto'; import { NotificationEntity } from '../notification/notification.entity'; @Injectable() -export class SignatureCommentService{ - +export class SignatureCommentService { constructor( private readonly signatureService: SignatureService, private readonly userService: UserService, private readonly s3Service: S3UtilService, ) {} - async createSignatureComment( // 댓글, 답글 생성하기 + async createSignatureComment( + // 댓글, 답글 생성하기 createCommentDto: CreateCommentDto, userId: number, signatureId: number, - parentCommentId?: number){ - + parentCommentId?: number, + ) { const comment = new SignatureCommentEntity(); - const user = await UserEntity.findOneOrFail({ where: { id: userId }}); - const signature = await SignatureEntity.findOneOrFail( { where: { id: signatureId }}); - + const user = await UserEntity.findOneOrFail({ where: { id: userId } }); + const signature = await SignatureEntity.findOneOrFail({ + where: { id: signatureId }, + }); - if( !user || !signature ) { + if (!user || !signature) { throw new NotFoundException('404 Not Found'); - } - else { - + } else { comment.user = user; comment.signature = signature; comment.content = createCommentDto.content; @@ -50,21 +53,22 @@ export class SignatureCommentService{ const notification = new NotificationEntity(); // parentCommentId가 존재할 경우 -> 답글 / 존재하지 않을 경우 -> 댓글 - if(parentCommentId){ // 대댓글: parentId는 파라미터로 받은 parentCommentId로 설정 + if (parentCommentId) { + // 대댓글: parentId는 파라미터로 받은 parentCommentId로 설정 - const parentComment = await SignatureCommentEntity.findOneOrFail( { - where:{ id: parentCommentId - }}); + const parentComment = await SignatureCommentEntity.findOneOrFail({ + where: { id: parentCommentId }, + }); - if( !parentComment ) throw new NotFoundException('404 Not Found'); + if (!parentComment) throw new NotFoundException('404 Not Found'); else { comment.parentComment = parentComment; await comment.save(); } notification.notificationReceiver = parentComment.user; - } - else{ // 댓글: parentId는 본인으로 설정 + } else { + // 댓글: parentId는 본인으로 설정 const savedComment = await comment.save(); savedComment.parentComment = savedComment; await savedComment.save(); @@ -82,58 +86,60 @@ export class SignatureCommentService{ } } - async getSignatureComment( // 댓글 가져오기 + async getSignatureComment( + // 댓글 가져오기 cursorPageOptionsDto: CursorPageOptionsDto, userId: number, signatureId: number, ) { - try{ - + try { // 1. 'cursorId'부터 오름차순 정렬된 댓글 'take'만큼 가져오기 const [comments, total] = await SignatureCommentEntity.findAndCount({ take: cursorPageOptionsDto.take, where: { id: MoreThan(cursorPageOptionsDto.cursorId), signature: { id: signatureId }, - parentComment: { id: Raw("SignatureCommentEntity.id") }, // 부모 댓글이 자기 자신인 댓글들만 가져오기 + parentComment: { id: Raw('SignatureCommentEntity.id') }, // 부모 댓글이 자기 자신인 댓글들만 가져오기 }, relations: { user: { profileImage: true }, parentComment: true, - signature:{ user: true, } + signature: { user: true }, }, order: { - parentComment: { id: "ASC" as any,}, - created: 'ASC' + parentComment: { id: 'ASC' as any }, + created: 'ASC', }, }); - const result: GetSignatureCommentDto[] = []; // 2. 각 부모 댓글의 답글들 찾아오기 - for(const comment of comments){ + for (const comment of comments) { console.log(comment); - result.push(await this.createSignatureCommentDto(comment,userId)); + result.push(await this.createSignatureCommentDto(comment, userId)); - const childrenComments = await SignatureCommentEntity.find({ // 답글 찾아오기 + const childrenComments = await SignatureCommentEntity.find({ + // 답글 찾아오기 where: { parentComment: { id: comment.id }, - id: Not(Raw("SignatureCommentEntity.parentComment.id")) + id: Not(Raw('SignatureCommentEntity.parentComment.id')), }, relations: { user: { profileImage: true }, parentComment: true, - signature:{ user: true, } + signature: { user: true }, }, order: { - created: 'ASC' + created: 'ASC', }, }); - for(const childComment of childrenComments){ + for (const childComment of childrenComments) { console.log(childComment); - result.push(await this.createSignatureCommentDto(childComment,userId)) + result.push( + await this.createSignatureCommentDto(childComment, userId), + ); } } @@ -152,19 +158,25 @@ export class SignatureCommentService{ cursor = lastDataPerScroll.id; } - const cursorPageMetaDto = new CursorPageMetaDto( - { cursorPageOptionsDto, total, hasNextData, cursor }); - - return new CursorPageDto( result, cursorPageMetaDto ); + const cursorPageMetaDto = new CursorPageMetaDto({ + cursorPageOptionsDto, + total, + hasNextData, + cursor, + }); - } - catch(e){ - console.log("Error on GetSignature: ",e); + return new CursorPageDto(result, cursorPageMetaDto); + } catch (e) { + console.log('Error on GetSignature: ', e); throw e; } } - async createSignatureCommentDto(comment: SignatureCommentEntity, userId: number){ // 댓글 DTO 만들기 + async createSignatureCommentDto( + comment: SignatureCommentEntity, + userId: number, + ) { + // 댓글 DTO 만들기 const writerProfile = new GetCommentWriterDto(); const getCommentDto = new GetSignatureCommentDto(); @@ -173,13 +185,12 @@ export class SignatureCommentService{ writerProfile.name = comment.user.nickname; // 로그인한 사용자가 댓글 작성자인지 확인 - if( userId == comment.user.id ) writerProfile.is_writer = true; - + if (userId == comment.user.id) writerProfile.is_writer = true; else writerProfile.is_writer = false; // 작성자 프로필 이미지 const image = comment.user.profileImage; - if(image == null) writerProfile.image = null; + if (image == null) writerProfile.image = null; else { const userImageKey = image.imageKey; writerProfile.image = await this.s3Service.getImageUrl(userImageKey); @@ -196,7 +207,8 @@ export class SignatureCommentService{ const createdTime = comment.created.getTime(); const updatedTime = comment.updated.getTime(); - if (Math.abs(createdTime - updatedTime) <= 2000) { // 두 시간 차가 2초 이하면 수정 안함 + if (Math.abs(createdTime - updatedTime) <= 2000) { + // 두 시간 차가 2초 이하면 수정 안함 getCommentDto.is_edited = false; } else { getCommentDto.is_edited = true; @@ -204,97 +216,103 @@ export class SignatureCommentService{ // 로그인한 사용자가 시그니처 작성하면 can_delete = true let can_delete = false; - if(comment.signature.user){ // 시그니처 작성자가 존재할 경우 - if(comment.signature.user.id == userId){ // 로그인한 사용자가 시그니처 작성자일 경우 댓글 삭제 가능 + if (comment.signature.user) { + // 시그니처 작성자가 존재할 경우 + if (comment.signature.user.id == userId) { + // 로그인한 사용자가 시그니처 작성자일 경우 댓글 삭제 가능 can_delete = true; } } getCommentDto.can_delete = can_delete; return getCommentDto; - } - async patchSignatureComment( // 댓글 수정하기 + async patchSignatureComment( + // 댓글 수정하기 userId: number, signatureId: number, commentId: number, - patchedComment: CreateCommentDto) { - + patchedComment: CreateCommentDto, + ) { // 시그니처 유효한지 확인 const signature = await SignatureEntity.findOne({ - where:{ id: signatureId }, - relations: { user: true } + where: { id: signatureId }, + relations: { user: true }, }); - if(!signature) throw new NotFoundException('존재하지 않는 시그니처입니다'); + if (!signature) throw new NotFoundException('존재하지 않는 시그니처입니다'); // 댓글 데이터 유효한지 확인 const comment = await SignatureCommentEntity.findOne({ - where:{ id: commentId }, - relations: { user: true } - }, - ); - if(!comment) throw new NotFoundException('존재하지 않는 댓글입니다'); - + where: { id: commentId }, + relations: { user: true }, + }); + if (!comment) throw new NotFoundException('존재하지 않는 댓글입니다'); let forbiddenUser = true; // 댓글 작성자가 로그인한 사용자 본인 혹은 시그니처 작성자가 맞는지 확인 - if(signature.user){ // 시그니처 작성자가 존재한다면 시그니처 작성자와 로그인한 사용자가 일치하는지 확인 - if( signature.user.id == userId ) forbiddenUser = false; + if (signature.user) { + // 시그니처 작성자가 존재한다면 시그니처 작성자와 로그인한 사용자가 일치하는지 확인 + if (signature.user.id == userId) forbiddenUser = false; } - if(comment.user.id){ // 댓글 작성자가 존재한다면 댓글 작성자와 로그인한 사용자가 일치하는지 확인 - if(comment.user.id == userId ) forbiddenUser = false; + if (comment.user.id) { + // 댓글 작성자가 존재한다면 댓글 작성자와 로그인한 사용자가 일치하는지 확인 + if (comment.user.id == userId) forbiddenUser = false; } - if(forbiddenUser) throw new ForbiddenException('댓글 수정 권한이 없습니다'); - + if (forbiddenUser) + throw new ForbiddenException('댓글 수정 권한이 없습니다'); // 댓글 수정하기 comment.content = patchedComment.content; await comment.save(); return comment.id; - } - async deleteSignatureComment(userId: number, signatureId: number, commentId: number) { + async deleteSignatureComment( + userId: number, + signatureId: number, + commentId: number, + ) { try { // 시그니처 유효한지 확인 const signature = await SignatureEntity.findOne({ where: { id: signatureId }, - relations: { user: true } + relations: { user: true }, }); - if (!signature) throw new NotFoundException('존재하지 않는 시그니처입니다'); + if (!signature) + throw new NotFoundException('존재하지 않는 시그니처입니다'); // 댓글 데이터 유효한지 확인 const comment = await SignatureCommentEntity.findOne({ - where: { id: commentId }, - relations: ['user', 'parentComment', 'signature'] - }, - ); + where: { id: commentId }, + relations: ['user', 'parentComment', 'signature'], + }); if (!comment) throw new NotFoundException('존재하지 않는 댓글입니다'); - let forbiddenUser = true; // 댓글 작성자가 로그인한 사용자 본인 혹은 시그니처 작성자가 맞는지 확인 - if(signature.user){ // 시그니처 작성자가 존재한다면 시그니처 작성자와 로그인한 사용자가 일치하는지 확인 - if( signature.user.id == userId ) forbiddenUser = false; + if (signature.user) { + // 시그니처 작성자가 존재한다면 시그니처 작성자와 로그인한 사용자가 일치하는지 확인 + if (signature.user.id == userId) forbiddenUser = false; } - if(comment.user.id){ // 댓글 작성자가 존재한다면 댓글 작성자와 로그인한 사용자가 일치하는지 확인 - if(comment.user.id == userId ) forbiddenUser = false; + if (comment.user.id) { + // 댓글 작성자가 존재한다면 댓글 작성자와 로그인한 사용자가 일치하는지 확인 + if (comment.user.id == userId) forbiddenUser = false; } - if(forbiddenUser) throw new ForbiddenException('댓글 삭제 권한이 없습니다'); - + if (forbiddenUser) + throw new ForbiddenException('댓글 삭제 권한이 없습니다'); // 해당 댓글이 부모 댓글인 경우 자식 댓글 모두 삭제 if (commentId == comment.parentComment.id) { - // 자식 댓글 모두 찾아오기 - const replyComments: SignatureCommentEntity[] = await SignatureCommentEntity.find({ - where: { parentComment: { id: commentId } } - }); + const replyComments: SignatureCommentEntity[] = + await SignatureCommentEntity.find({ + where: { parentComment: { id: commentId } }, + }); // 자식 댓글 모두 삭제 for (const reply of replyComments) { @@ -303,17 +321,15 @@ export class SignatureCommentService{ // 자식 모두 삭제했으면 부모 댓글 삭제 await comment.softRemove(); - - } - else{ // 자식 댓글 없는 경우 본인만 삭제 + } else { + // 자식 댓글 없는 경우 본인만 삭제 await comment.softRemove(); } return commentId; - } catch (error) { console.log(error); throw error; } } -} \ No newline at end of file +} diff --git a/src/signature/signature.controller.ts b/src/signature/signature.controller.ts index ac41eb9..6516a47 100644 --- a/src/signature/signature.controller.ts +++ b/src/signature/signature.controller.ts @@ -1,6 +1,16 @@ // signature.controller.ts -import { Body, Controller, Delete, Get, Param, Patch, Post, Req, UseGuards } from '@nestjs/common'; +import { + Body, + Controller, + Delete, + Get, + Param, + Patch, + Post, + Req, + UseGuards, +} from '@nestjs/common'; import { SignatureService } from './signature.service'; import { CreateSignatureDto } from './dto/signature/create-signature.dto'; import { ResponseCode } from '../response/response-code.enum'; @@ -20,24 +30,24 @@ export class SignatureController { @Get('/') // 시그니처 탭 메인: 내 시그니처 목록 @UseGuards(UserGuard) - async getMySignature(@Req() req: Request): Promise> { - + async getMySignature( + @Req() req: Request, + ): Promise> { const result = await this.signatureService.homeSignature(req.user.id); - if(!result){ + if (!result) { return new ResponseDto( ResponseCode.GET_MY_SIGNATURE_FAIL, false, - "내 시그니처 가져오기 실패", - null + '내 시그니처 가져오기 실패', + null, ); - } - else{ + } else { return new ResponseDto( ResponseCode.GET_MY_SIGNATURES_SUCCESS, true, - "내 시그니처 가져오기 성공", - result + '내 시그니처 가져오기 성공', + result, ); } } @@ -46,23 +56,27 @@ export class SignatureController { @UseGuards(UserGuard) async createNewSignature( @Body() newSignature: CreateSignatureDto, - @Req() req: Request + @Req() req: Request, ): Promise> { - const result = await this.signatureService.createSignature(newSignature, req.user.id); + const result = await this.signatureService.createSignature( + newSignature, + req.user.id, + ); - if(!result){ + if (!result) { return new ResponseDto( ResponseCode.SIGNATURE_CREATION_FAIL, false, - "시그니처 생성에 실패했습니다", - null); - } - else{ + '시그니처 생성에 실패했습니다', + null, + ); + } else { return new ResponseDto( ResponseCode.SIGNATURE_CREATED, true, - "시그니처 기록하기 성공", - result); + '시그니처 기록하기 성공', + result, + ); } } @@ -70,17 +84,24 @@ export class SignatureController { @UseGuards(UserGuard) async patchSignatureLike( @Param('signatureId') signatureId: number, - @Req() req: Request + @Req() req: Request, ): Promise> { - try{ - + try { // [1] 이미 좋아요 했는지 확인 - const liked: SignatureLikeEntity= await this.signatureService.findIfAlreadyLiked(req.user.id,signatureId); + const liked: SignatureLikeEntity = + await this.signatureService.findIfAlreadyLiked( + req.user.id, + signatureId, + ); let result = new SignatureEntity(); - const likeSignatureDto= new LikeSignatureDto(); + const likeSignatureDto = new LikeSignatureDto(); - if(liked){ // 이미 좋아요했던 시그니처라면 좋아요 삭제 - result = await this.signatureService.deleteLikeOnSignature(liked,signatureId); + if (liked) { + // 이미 좋아요했던 시그니처라면 좋아요 삭제 + result = await this.signatureService.deleteLikeOnSignature( + liked, + signatureId, + ); likeSignatureDto.liked = result.liked; likeSignatureDto.signatureId = result.id; @@ -88,11 +109,14 @@ export class SignatureController { ResponseCode.DELETE_LIKE_ON_SIGNATURE_SUCCESS, true, '시그니처 좋아요 취소하기 성공', - likeSignatureDto + likeSignatureDto, + ); + } else { + // 좋아요 한적 없으면 시그니처 좋아요 추가 + result = await this.signatureService.addLikeOnSignature( + req.user.id, + signatureId, ); - - }else{ // 좋아요 한적 없으면 시그니처 좋아요 추가 - result = await this.signatureService.addLikeOnSignature(req.user.id,signatureId); likeSignatureDto.liked = result.liked; likeSignatureDto.signatureId = result.id; @@ -100,12 +124,11 @@ export class SignatureController { ResponseCode.LIKE_ON_SIGNATURE_CREATED, true, '시그니처 좋아요 성공', - likeSignatureDto + likeSignatureDto, ); } - - }catch(error){ - console.log('addSignatureLike: ', error ); + } catch (error) { + console.log('addSignatureLike: ', error); throw error; } } @@ -114,110 +137,113 @@ export class SignatureController { @UseGuards(UserGuard) async getSignatureDetail( @Req() req: Request, - @Param('signatureId') signatureId: number + @Param('signatureId') signatureId: number, ): Promise> { - - try{ + try { // 임시로 토큰이 아닌 유저 아이디 받도록 구현 -> 리펙토링 예정 - const result = await this.signatureService.detailSignature(req.user.id, signatureId); + const result = await this.signatureService.detailSignature( + req.user.id, + signatureId, + ); - if(result == null){ + if (result == null) { return new ResponseDto( ResponseCode.SIGNATURE_NOT_FOUND, false, - "존재하지 않는 시그니처 입니다", - result + '존재하지 않는 시그니처 입니다', + result, ); } - if(result.author.is_followed){ // 작성자가 본인이 아닌 경우 - if(result.author._id == null){ // 작성자가 탈퇴한 경우 + if (result.author.is_followed) { + // 작성자가 본인이 아닌 경우 + if (result.author._id == null) { + // 작성자가 탈퇴한 경우 return new ResponseDto( ResponseCode.GET_SIGNATURE_DETAIL_SUCCESS, true, - "시그니처 상세보기 성공: 작성자 탈퇴", - result + '시그니처 상세보기 성공: 작성자 탈퇴', + result, ); - } - else{ + } else { return new ResponseDto( ResponseCode.GET_SIGNATURE_DETAIL_SUCCESS, true, - "시그니처 상세보기 성공: 메이트의 시그니처", - result + '시그니처 상세보기 성공: 메이트의 시그니처', + result, ); } - } - else{ // 작성자가 본인인 경우 author 없음 + } else { + // 작성자가 본인인 경우 author 없음 return new ResponseDto( ResponseCode.GET_SIGNATURE_DETAIL_SUCCESS, true, - "시그니처 상세보기 성공: 내 시그니처", - result + '시그니처 상세보기 성공: 내 시그니처', + result, ); } - } - catch(error){ - console.log('Error on signatureId: ',error); + } catch (error) { + console.log('Error on signatureId: ', error); throw error; } - } @Patch('/:signatureId') // 시그니처 수정하기 async patchSignature( @Body() patchSignatureDto: CreateSignatureDto, - @Param('signatureId') signatureId: number + @Param('signatureId') signatureId: number, ): Promise> { - try{ + try { // 임시로 토큰이 아닌 유저 아이디 받도록 구현 -> 리펙토링 예정 - const result = await this.signatureService.patchSignature(signatureId, patchSignatureDto); + const result = await this.signatureService.patchSignature( + signatureId, + patchSignatureDto, + ); - if(result == null) { + if (result == null) { return new ResponseDto( ResponseCode.SIGNATURE_NOT_FOUND, false, - "존재하지 않는 시그니처 입니다", - result + '존재하지 않는 시그니처 입니다', + result, ); } return new ResponseDto( ResponseCode.PATCH_SIGNATURE_SUCCESS, true, - "시그니처 수정하기 성공", - result + '시그니처 수정하기 성공', + result, ); - } - catch(error){ + } catch (error) { console.log(error); return new ResponseDto( ResponseCode.SIGNATURE_PATCH_FAIL, false, - "시그니처 수정하기 실패", - null + '시그니처 수정하기 실패', + null, ); } - } @Delete('/:signatureId') // 시그니처 삭제하기 async deleteSignature( - @Param('signatureId') signatureId: number + @Param('signatureId') signatureId: number, ): Promise> { - try{ + try { // 임시로 토큰이 아닌 유저 아이디 받도록 구현 -> 리펙토링 예정 // [1] 시그니처 가져오기 - const signature:SignatureEntity = await SignatureEntity.findSignatureById(signatureId); - console.log("시그니처 정보: ", signature); + const signature: SignatureEntity = + await SignatureEntity.findSignatureById(signatureId); + console.log('시그니처 정보: ', signature); - if(signature == null) { + if (signature == null) { return new ResponseDto( ResponseCode.SIGNATURE_NOT_FOUND, false, - "존재하지 않는 시그니처 입니다", - null + '존재하지 않는 시그니처 입니다', + null, ); } @@ -227,17 +253,16 @@ export class SignatureController { return new ResponseDto( ResponseCode.DELETE_SIGNATURE_SUCCESS, true, - "시그니처 삭제 성공", - null + '시그니처 삭제 성공', + null, ); - } - catch(error){ + } catch (error) { console.log(error); return new ResponseDto( ResponseCode.SIGNATURE_DELETE_FAIL, false, - "시그니처 삭제 실패", - null + '시그니처 삭제 실패', + null, ); } } @@ -246,27 +271,28 @@ export class SignatureController { @UseGuards(UserGuard) async getSignatureLikeList( @Req() req: Request, - @Param('signatureId') signatureId: number + @Param('signatureId') signatureId: number, ): Promise> { - try{ - const getLikeListDto:GetLikeListDto = await this.signatureService.getSignatureLikeList(req.user.id, signatureId); + try { + const getLikeListDto: GetLikeListDto = + await this.signatureService.getSignatureLikeList( + req.user.id, + signatureId, + ); return new ResponseDto( ResponseCode.GET_LIKE_SIGNATURE_PROFILES_SUCCESS, true, - "시그니처 좋아요 목록 불러오기 성공", - getLikeListDto + '시그니처 좋아요 목록 불러오기 성공', + getLikeListDto, ); - - } - catch(error){ + } catch (error) { return new ResponseDto( ResponseCode.GET_LIKE_SIGNATURE_PROFILES_FAIL, false, - "시그니처 좋아요 목록 불러오기 실패", - null + '시그니처 좋아요 목록 불러오기 실패', + null, ); } } - } diff --git a/src/signature/signature.module.ts b/src/signature/signature.module.ts index 0e20e36..66b80d4 100644 --- a/src/signature/signature.module.ts +++ b/src/signature/signature.module.ts @@ -3,10 +3,6 @@ import { Module } from '@nestjs/common'; import { SignatureService } from './signature.service'; import { SignatureController } from './signature.controller'; -import { SignatureEntity } from './domain/signature.entity'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { DataSource } from 'typeorm'; -import { EntityManager } from 'typeorm'; import { UserService } from '../user/user.service'; import { S3UtilService } from '../utils/S3.service'; import { SignatureCommentController } from './signature.comment.controller'; @@ -14,6 +10,11 @@ import { SignatureCommentService } from './signature.comment.service'; @Module({ controllers: [SignatureController, SignatureCommentController], - providers: [SignatureService, SignatureCommentService, UserService, S3UtilService], + providers: [ + SignatureService, + SignatureCommentService, + UserService, + S3UtilService, + ], }) export class SignatureModule {} diff --git a/src/signature/signature.service.ts b/src/signature/signature.service.ts index 1ee3fc3..a668598 100644 --- a/src/signature/signature.service.ts +++ b/src/signature/signature.service.ts @@ -22,7 +22,6 @@ import { LikeProfileDto } from './dto/like/like-profile.dto'; import { S3UtilService } from '../utils/S3.service'; import { ResponsePageSignatureDto } from './dto/signature/response-page-signature.dto'; import { NotificationEntity } from '../notification/notification.entity'; -import { NotificationService } from '../notification/notification.service'; @Injectable() export class SignatureService { @@ -94,10 +93,7 @@ export class SignatureService { async homeSignature(userId: number): Promise { try { console.log('userId; ', userId); - return this.findMySignature( - userId, - ); - + return this.findMySignature(userId); } catch (error) { // 예외 처리 console.error('Error on HomeSignature: ', error); @@ -109,7 +105,7 @@ export class SignatureService { const mySignatureList: HomeSignatureDto[] = []; const signatures = await SignatureEntity.find({ where: { user: { id: user_id } }, - order: { created: 'DESC' } // 내가 작성한 시그니처 최신 순으로 보여주도록 + order: { created: 'DESC' }, // 내가 작성한 시그니처 최신 순으로 보여주도록 }); for (const signature of signatures) { @@ -160,7 +156,8 @@ export class SignatureService { // [2] 시그니처 작성자 정보 가져오기 const authorDto: AuthorSignatureDto = new AuthorSignatureDto(); - if (!signature.user.isQuit) { // 유저가 탈퇴하지 않았다면 + if (!signature.user.isQuit) { + // 유저가 탈퇴하지 않았다면 authorDto._id = signature.user.id; authorDto.name = signature.user.nickname; @@ -289,14 +286,14 @@ export class SignatureService { signatureId: number, ) { // [1] 해당 좋아요 기록 삭제 - const deleted_like = await SignatureLikeEntity.softRemove(signatureLike); + await SignatureLikeEntity.softRemove(signatureLike); // [2] 시그니처 좋아요 개수 -1 const signature: SignatureEntity = await SignatureEntity.findSignatureById( signatureId, ); signature.liked--; - const newSignature = await SignatureEntity.save(signature); + await SignatureEntity.save(signature); return signature; } @@ -374,10 +371,7 @@ export class SignatureService { )}`; // Base64 이미지 업로드 - const uploadedImage = await this.s3Service.putObjectFromBase64( - key, - patchedPage.image, - ); + await this.s3Service.putObjectFromBase64(key, patchedPage.image); // 이미지 키 저장 originalPage.image = key; diff --git a/src/user/optional.user.guard.ts b/src/user/optional.user.guard.ts index 2b47c05..6e16b2c 100644 --- a/src/user/optional.user.guard.ts +++ b/src/user/optional.user.guard.ts @@ -37,8 +37,8 @@ export class OptionalUserGuard implements CanActivate { } catch (error) { return false; } - } - else{ // 토큰이 없는 경우 + } else { + // 토큰이 없는 경우 request.user = null; } diff --git a/src/user/user.following.entity.ts b/src/user/user.following.entity.ts index 31758c7..65ad120 100644 --- a/src/user/user.following.entity.ts +++ b/src/user/user.following.entity.ts @@ -1,9 +1,12 @@ import { - BaseEntity, CreateDateColumn, DeleteDateColumn, + BaseEntity, + CreateDateColumn, + DeleteDateColumn, Entity, JoinColumn, ManyToOne, - PrimaryGeneratedColumn, UpdateDateColumn, + PrimaryGeneratedColumn, + UpdateDateColumn, } from 'typeorm'; import { UserEntity } from './user.entity'; diff --git a/src/user/user.profile.image.entity.ts b/src/user/user.profile.image.entity.ts index afc8172..c103f05 100644 --- a/src/user/user.profile.image.entity.ts +++ b/src/user/user.profile.image.entity.ts @@ -10,7 +10,6 @@ import { UpdateDateColumn, } from 'typeorm'; import { UserEntity } from './user.entity'; -import { User } from 'aws-sdk/clients/budgets'; @Entity() export class UserProfileImageEntity extends BaseEntity { @@ -34,7 +33,10 @@ export class UserProfileImageEntity extends BaseEntity { deleted: Date; static async findImageKey(userEntity): Promise { - const imageEntity : UserProfileImageEntity = await UserProfileImageEntity.findOneOrFail({ where: { user : userEntity } }); + const imageEntity: UserProfileImageEntity = + await UserProfileImageEntity.findOneOrFail({ + where: { user: userEntity }, + }); const imageKey = imageEntity.imageKey; return imageKey; diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 975d893..c8bd25e 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -13,7 +13,6 @@ import { RuleInvitationEntity } from '../rule/domain/rule.invitation.entity'; import * as md5 from 'md5'; import { DiaryEntity } from '../diary/models/diary.entity'; import { S3UtilService } from '../utils/S3.service'; -import {CommentEntity} from "../comment/domain/comment.entity"; @Injectable() export class UserService { @@ -451,7 +450,7 @@ export class UserService { try { return await UserFollowingEntity.find({ where: { - followUser: { id: userId, isQuit: false }, + followUser: { id: userId, isQuit: false }, user: { isQuit: false }, }, relations: { user: { profileImage: true } }, @@ -516,22 +515,19 @@ export class UserService { await user.save(); const followings = await UserFollowingEntity.find({ - where: [ - {user: {id: userId}}, - {followUser: {id: userId}} - ] + where: [{ user: { id: userId } }, { followUser: { id: userId } }], }); - for(const following of followings) { + for (const following of followings) { console.log('삭제될 팔로잉 테이블 ID : ', following.id); await following.softRemove(); } const ruleInvitations = await RuleInvitationEntity.find({ - where: {member: {id: userId}} + where: { member: { id: userId } }, }); - for(const invitation of ruleInvitations) { + for (const invitation of ruleInvitations) { console.log('삭제될 규칙 초대 테이블 ID : ', invitation.id); await invitation.softRemove(); } @@ -563,7 +559,7 @@ export class UserService { const followingMates = await UserEntity.find({ where: { follower: { user: { id: userId } }, - isQuit: false, // 탈퇴한 메이트는 팔로잉 목록에서 제외 + isQuit: false, // 탈퇴한 메이트는 팔로잉 목록에서 제외 }, }); return followingMates; diff --git a/src/utils/S3.controller.ts b/src/utils/S3.controller.ts index d7a2e91..8c2f049 100644 --- a/src/utils/S3.controller.ts +++ b/src/utils/S3.controller.ts @@ -1,22 +1,23 @@ // S3.controller.ts - -import { Body, Controller, Get, Post, Put } from '@nestjs/common'; +import { Body, Controller, Get } from '@nestjs/common'; import { S3UtilService } from './S3.service'; @Controller('image') -export class S3UtilController{ - constructor(private readonly s3Service:S3UtilService) {} +export class S3UtilController { + constructor(private readonly s3Service: S3UtilService) {} @Get('/signature') - GetPresignedUrlForSignature() { // 시그니처 이미지 업로드 요청시 + GetPresignedUrlForSignature() { + // 시그니처 이미지 업로드 요청시 return this.s3Service.GetPresignedUrlForSignature(); } @Get('/test') - TestImageUrlWithKey( //presigned URL 잘 보내졌나 테스트용 - @Body('key') key: string - ){ - return this.s3Service.TestImageUrlWithKey(key); + TestImageUrlWithKey( + //presigned URL 잘 보내졌나 테스트용 + @Body('key') key: string, + ) { + return this.s3Service.TestImageUrlWithKey(key); } -} \ No newline at end of file +} diff --git a/src/utils/S3.presignedUrl.dto.ts b/src/utils/S3.presignedUrl.dto.ts index bdf93e4..824a24a 100644 --- a/src/utils/S3.presignedUrl.dto.ts +++ b/src/utils/S3.presignedUrl.dto.ts @@ -1,6 +1,6 @@ // S3.presignedUrl.dto.ts -export class S3PresignedUrlDto{ +export class S3PresignedUrlDto { key: string; url: string; -} \ No newline at end of file +} diff --git a/src/utils/S3.service.ts b/src/utils/S3.service.ts index 80887ce..eb8e1e0 100644 --- a/src/utils/S3.service.ts +++ b/src/utils/S3.service.ts @@ -62,11 +62,12 @@ export class S3UtilService { } public async GetPresignedUrlForSignature(): Promise { - - const s3PresignedUrlDto:S3PresignedUrlDto= new S3PresignedUrlDto(); + const s3PresignedUrlDto: S3PresignedUrlDto = new S3PresignedUrlDto(); // 이미지 키 생성: 프론트에서는 업로드 후 백엔드에 키값을 보내줘야함 - s3PresignedUrlDto.key = `signature/${this.generateRandomImageKey('signature.png')}`; + s3PresignedUrlDto.key = `signature/${this.generateRandomImageKey( + 'signature.png', + )}`; // 프론트에서 이미지를 업로드할 presignedUrl s3PresignedUrlDto.url = await this.getPresignedUrl(s3PresignedUrlDto.key);