Skip to content

Commit 77e8074

Browse files
committed
feat: 게시물 response 응답값 수정
1 parent c2c7e9e commit 77e8074

21 files changed

+246
-179
lines changed

src/clothing/clothing.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common';
22
import { InjectRepository } from '@nestjs/typeorm';
33
import { QueryRunner, Repository } from 'typeorm';
44
import { Clothing } from 'src/common/entities/clothing.entity';
5-
import { UploadClothingDto } from 'src/post/dtos/post.request';
5+
import { UploadClothingDto } from 'src/post/dto/request/post.request';
66
import { DataNotFoundException } from 'src/common/exception/service.exception';
7-
import { PatchClothingDto } from 'src/post/dtos/post.request';
7+
import { PatchClothingDto } from 'src/post/dto/request/post.request';
88

99
@Injectable()
1010
export class ClothingService {

src/common/entities/matching.entity.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { BaseEntity } from './base.entity';
33
import { User } from './user.entity';
44
import { ChatRoom } from './chat-room.entity';
55
import { ApiProperty } from '@nestjs/swagger';
6+
import { MatchingRequestStatusEnum } from '../enum/matchingRequestStatus';
67

78
@Entity('Matching')
89
export class Matching extends BaseEntity {
@@ -23,13 +24,13 @@ export class Matching extends BaseEntity {
2324
})
2425
message!: string;
2526

26-
@Column({ type: 'enum', enum: ['pending', 'accepted', 'rejected'] })
27+
@Column({ type: 'enum', enum: MatchingRequestStatusEnum })
2728
@ApiProperty({
28-
enum: ['pending', 'accepted', 'rejected'],
29+
enum: MatchingRequestStatusEnum,
2930
description: '매칭 상태',
3031
example: 'pending',
3132
})
32-
requestStatus: 'pending' | 'accepted' | 'rejected' = 'pending';
33+
requestStatus: MatchingRequestStatusEnum = MatchingRequestStatusEnum.PENDING;
3334

3435
@Column({ type: 'datetime', nullable: true })
3536
rejectedAt: Date = null;

src/common/entities/post.entity.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { PostLike } from './post-like.entity';
77
import { PostStyletag } from './post-styletag.entity';
88
import { PostClothing } from './post-clothing.entity';
99
import { PostReport } from './post-report.entity';
10-
1110
@Entity('Post')
1211
export class Post extends BaseEntity {
1312
@ManyToOne(() => User, (user) => user.posts)
@@ -38,15 +37,16 @@ export class Post extends BaseEntity {
3837

3938
@OneToMany(() => PostReport, (postReport) => postReport.post)
4039
postReports!: PostReport[];
41-
images: string[];
40+
41+
images: string[];
4242

4343
// 댓글 수
4444
get commentCount(): number {
45-
return this.postComments? this.postComments.length : 0;
45+
return this.postComments ? this.postComments.length : 0;
4646
}
4747

4848
// Like 수
4949
get likeCount(): number {
50-
return this.postLikes? this.postLikes.length : 0;
50+
return this.postLikes ? this.postLikes.length : 0;
5151
}
5252
}

src/common/entities/user.entity.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ export class User extends BaseEntity {
8585
sentChatMessages?: ChatMessage[];
8686

8787
@OneToMany(() => Matching, (matching) => matching.requester)
88-
requestedMatchings?: Matching[];
88+
requestedMatchings: Matching[];
8989

9090
@OneToMany(() => Matching, (matching) => matching.target)
91-
targetedMatchings?: Matching[];
91+
targetedMatchings: Matching[];
9292

9393
@OneToMany(() => PostLike, (postLike) => postLike.user)
9494
postLikes!: PostLike[];
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum MatchingRequestStatusEnum {
2+
PENDING = 'pending',
3+
ACCEPTED = 'accepted',
4+
REJECTED = 'rejected',
5+
}

src/common/response/page.dto.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { IsArray } from 'class-validator';
22
import { PageMetaDto } from './page-meta.dto';
33
import { ApiProperty } from '@nestjs/swagger';
4-
import { GetAllPostsResponse } from '../../post/dtos/all-posts.response';
4+
import { GetAllPostsResponse } from '../../post/dto/all-posts.response';
55
import {
66
GetMyPostsResponse,
77
GetOtherPostsResponse,
8-
} from '../../post/dtos/user-posts.response';
8+
} from '../../post/dto/user-posts.response';
99

1010
export class PageDto<T> {
1111
@ApiProperty({

src/matching/matching.controller.ts

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ export class MatchingController {
7575
throw DataNotFoundException('신청 유저의 게시물이 존재하지 않습니다.');
7676
}
7777

78+
if (
79+
await this.matchingService.getMatchingByUserId(
80+
body.requesterId,
81+
body.targetId,
82+
)
83+
)
84+
throw InvalidInputValueException('이미 매칭 요청을 보냈습니다.');
85+
7886
const chatRoom = await this.matchingService.createMatching(body);
7987
return new BaseResponse<PostMatchingResponse>(true, 'SUCCESS', {
8088
chatRoomId: chatRoom.id,

src/matching/matching.service.ts

+34-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ChatMessageService } from 'src/chat-message/chat-message.service';
1414
import { ChatRoom } from 'src/common/entities/chat-room.entity';
1515
import { InjectRepository } from '@nestjs/typeorm';
1616
import { GetMatchingsResponse } from './dto/matching.response';
17+
import { MatchingRequestStatusEnum } from 'src/common/enum/matchingRequestStatus';
1718

1819
@Injectable()
1920
export class MatchingService {
@@ -24,6 +25,35 @@ export class MatchingService {
2425
private readonly chatMessageService: ChatMessageService,
2526
private readonly dataSource: DataSource,
2627
) {}
28+
async getMatchingByUserId(
29+
requesterId: number,
30+
targetId: number,
31+
): Promise<Matching> {
32+
return await this.matchingRepository.findOne({
33+
where: [
34+
{
35+
requester: { id: requesterId },
36+
target: { id: targetId },
37+
status: 'activated',
38+
},
39+
{
40+
requester: { id: targetId },
41+
target: { id: requesterId },
42+
status: 'activated',
43+
},
44+
],
45+
});
46+
}
47+
48+
async getMatchingsByCurrentId(currentUserId: number): Promise<Matching[]> {
49+
return await this.matchingRepository.find({
50+
relations: ['requester', 'target'],
51+
where: [
52+
{ requester: { id: currentUserId }, status: 'activated' },
53+
{ target: { id: currentUserId }, status: 'activated' },
54+
],
55+
});
56+
}
2757

2858
async createMatching(body: CreateMatchingReqeust): Promise<ChatRoom> {
2959
let matching, chatRoom;
@@ -68,10 +98,10 @@ export class MatchingService {
6898

6999
try {
70100
if (body.requestStatus === 'accept') {
71-
matching.requestStatus = 'accepted';
101+
matching.requestStatus = MatchingRequestStatusEnum.ACCEPTED;
72102
matching.acceptedAt = new Date();
73103
} else if (body.requestStatus === 'reject') {
74-
matching.requestStatus = 'rejected';
104+
matching.requestStatus = MatchingRequestStatusEnum.REJECTED;
75105
matching.rejectedAt = new Date();
76106
}
77107

@@ -157,13 +187,13 @@ export class MatchingService {
157187
{
158188
requester: { id: requesterId },
159189
target: { id: targetId },
160-
requestStatus: 'accepted',
190+
requestStatus: MatchingRequestStatusEnum.ACCEPTED,
161191
status: 'activated',
162192
},
163193
{
164194
requester: { id: targetId },
165195
target: { id: requesterId },
166-
requestStatus: 'accepted',
196+
requestStatus: MatchingRequestStatusEnum.ACCEPTED,
167197
status: 'activated',
168198
},
169199
],

src/post-clothing/post-clothing.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { ClothingService } from 'src/clothing/clothing.service';
44
import { Clothing } from 'src/common/entities/clothing.entity';
55
import { PostClothing } from 'src/common/entities/post-clothing.entity';
66
import { Post } from 'src/common/entities/post.entity';
7-
import { UploadClothingDto } from 'src/post/dtos/post.request';
8-
import { PatchClothingDto } from 'src/post/dtos/post.request';
7+
import { UploadClothingDto } from 'src/post/dto/request/post.request';
8+
import { PatchClothingDto } from 'src/post/dto/request/post.request';
99
import { QueryRunner, Repository } from 'typeorm';
1010

1111
@Injectable()

src/post-image/post-image.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
33
import { PostImage } from 'src/common/entities/post-image.entity';
44
import { Repository, QueryRunner } from 'typeorm';
55
import { Post } from 'src/common/entities/post.entity';
6-
import { UploadImageDto } from 'src/post/dtos/post.request';
6+
import { UploadImageDto } from 'src/post/dto/request/post.request';
77
import { InvalidInputValueException } from 'src/common/exception/service.exception';
88

99
@Injectable()

src/post/dto/all-posts.response.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import dayjs from 'dayjs';
3+
import { GetAllPostDto, UserDto } from './dto/get-all-posts.dto';
4+
import { MatchingRequestStatusEnum } from '../../common/enum/matchingRequestStatus';
5+
import { Matching } from 'src/common/entities/matching.entity';
6+
7+
export class PostDto extends GetAllPostDto {
8+
@ApiProperty({
9+
description: '게시글에 좋아요 눌렀는지 여부입니다.',
10+
example: true,
11+
})
12+
isPostLike: boolean;
13+
14+
@ApiProperty({
15+
required: false,
16+
enum: MatchingRequestStatusEnum,
17+
description: '매칭 요청 상태입니다.',
18+
})
19+
requestStatus?: MatchingRequestStatusEnum | null;
20+
21+
constructor(
22+
post: GetAllPostDto,
23+
currentUserId: number,
24+
requestStatus?: MatchingRequestStatusEnum | null,
25+
) {
26+
super();
27+
this.id = post.id;
28+
this.content = post.content;
29+
this.createdAt = dayjs(post.createdAt).format('YYYY-MM-DDTHH:mm:ssZ');
30+
this.postImages = post.postImages ?? [];
31+
this.isPostLike =
32+
post.postLikesUserIds?.some((like) => like === currentUserId) || false;
33+
this.requestStatus = requestStatus;
34+
this.user = new UserDto(post.user);
35+
}
36+
}
37+
38+
export class GetAllPostsResponse {
39+
@ApiProperty({
40+
type: [PostDto],
41+
description: '조회된 게시글 목록입니다.',
42+
})
43+
post: PostDto[];
44+
45+
constructor(
46+
posts: GetAllPostDto[],
47+
currentUserId: number,
48+
matchings?: Matching[],
49+
) {
50+
this.post = posts.map((post) => {
51+
const matching = matchings?.find(
52+
(matching) =>
53+
matching.requester.id === post.user.id ||
54+
matching.target.id === post.user.id,
55+
);
56+
return new PostDto(post, currentUserId, matching?.requestStatus ?? null);
57+
});
58+
}
59+
}

src/post/dto/dto/get-all-posts.dto.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { ApiProperty, PickType } from '@nestjs/swagger';
2+
import { PostImage } from 'src/common/entities/post-image.entity';
3+
import { Post } from 'src/common/entities/post.entity';
4+
import { User } from 'src/common/entities/user.entity';
5+
6+
// 게시물 작성자 정보를 위한 DTO
7+
export class UserDto extends PickType(User, [
8+
'id',
9+
'nickname',
10+
'profilePictureUrl',
11+
]) {
12+
constructor(user: UserDto) {
13+
super();
14+
this.id = user.id;
15+
this.nickname = user.nickname;
16+
this.profilePictureUrl = user.profilePictureUrl;
17+
}
18+
}
19+
20+
// 게시물 이미지 정보를 위한 DTO
21+
export class PostImageDto extends PickType(PostImage, [
22+
'id',
23+
'url',
24+
'orderNum',
25+
]) {
26+
constructor(postImage: PostImage) {
27+
super();
28+
this.id = postImage.id;
29+
this.url = postImage.url;
30+
this.orderNum = postImage.orderNum;
31+
}
32+
}
33+
34+
// 각 게시물 정보 DTO
35+
export class GetAllPostDto extends PickType(Post, ['id', 'content']) {
36+
@ApiProperty({ type: UserDto })
37+
user: UserDto; // 유저 정보
38+
39+
@ApiProperty({
40+
type: String,
41+
description: '게시물 작성 시간',
42+
example: '2021-08-31T00:00:00Z',
43+
})
44+
createdAt: string; // 게시물 작성 시간
45+
46+
@ApiProperty({ type: PostImageDto, isArray: true })
47+
postImages: PostImageDto[]; // 게시물 이미지
48+
49+
@ApiProperty({
50+
type: [Number],
51+
description: '좋아요 IDs',
52+
example: [1, 2, 3],
53+
})
54+
postLikesUserIds: number[]; // 좋아요 목록
55+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)