-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add base operations of getting meets
- Loading branch information
Showing
14 changed files
with
221 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,119 @@ | ||
import { Controller, Get, UseGuards, Query } from '@nestjs/common'; | ||
import { | ||
Controller, | ||
Get, | ||
UseGuards, | ||
Query, | ||
BadRequestException, | ||
Param, | ||
} from '@nestjs/common'; | ||
import { FcmService } from '../fcm/fcm.service'; | ||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; | ||
import { JwtAuthGuard } from '../auth/guard/jwt.auth.guard'; | ||
import { MeetService } from './meet.service'; | ||
import { RoleGuard } from '../auth/guard/role.guard'; | ||
import { AuthUserDto } from 'src/dtos/common/auth.user.dto'; | ||
import { AuthUser } from 'src/lib/decorators/auth.user.decorator'; | ||
import { Role } from 'src/lib/enums/user.role.enum'; | ||
import { | ||
MeetCommentRequestDto, | ||
MeetCommentResponseDto, | ||
MeetGetRequestDto, | ||
AuthUserDto, | ||
MeetDetailRequestDto, | ||
MeetDetailResponseDto, | ||
MeetRequestDto, | ||
MeetResponseDto, | ||
PaginationDto, | ||
} from 'src/dtos'; | ||
import { AuthUser } from 'src/lib/decorators'; | ||
import { paginate } from 'src/lib/utils/pagination.util'; | ||
import { UserService } from '../user/user.service'; | ||
import { | ||
FindOptionsWhere, | ||
In, | ||
IsNull, | ||
LessThanOrEqual, | ||
MoreThanOrEqual, | ||
} from 'typeorm'; | ||
import { Meet } from 'src/entities'; | ||
import { productArray } from 'src/lib/utils/array.util'; | ||
|
||
@Controller('meet') | ||
@ApiTags('meet') | ||
export class MeetController { | ||
constructor( | ||
private readonly meetService: MeetService, | ||
private readonly userService: UserService, | ||
private readonly fcmService: FcmService, | ||
) {} | ||
|
||
@Get('/') | ||
@Get() | ||
@UseGuards(JwtAuthGuard, RoleGuard(Role.USER)) | ||
@ApiOperation({ summary: 'isTag에 따라 category 포함해 meet를 반환' }) | ||
@ApiOperation({ | ||
summary: '참여 가능한 모임 목록을 반환; 성별, 나이, 시간, (구독) 필터링', | ||
}) | ||
@ApiBearerAuth() | ||
async getMeet( | ||
async getMeets( | ||
@AuthUser() user: AuthUserDto, | ||
@Query() payload: MeetGetRequestDto, | ||
@Query() payload: MeetRequestDto, | ||
): Promise<MeetResponseDto[]> { | ||
const { isTag } = payload; | ||
const result = await this.meetService.getMeets(user, isTag); | ||
const { id: userId } = user; | ||
const { subscribed, ...pagination } = payload; | ||
|
||
const { gender, age, subscriptions } = | ||
await this.userService.getUserWithTagsById(userId); | ||
if (!gender || !age) { | ||
throw new BadRequestException( | ||
'사용자의 성별 또는 나이가 입력되지 않았습니다.', | ||
); | ||
} | ||
|
||
const tagOption = subscribed | ||
? await (async () => { | ||
const tagIds = subscriptions.map((sub) => sub.tagId); | ||
return { tagId: In(tagIds) }; | ||
})() | ||
: {}; | ||
const expiredOption = { meetTime: MoreThanOrEqual(new Date()) }; | ||
|
||
const where = productArray<FindOptionsWhere<Meet>>([ | ||
[{ ...tagOption, ...expiredOption }], | ||
[{ gender: IsNull() }, { gender }], | ||
[{ minAge: IsNull() }, { minAge: LessThanOrEqual(age) }], | ||
[{ maxAge: IsNull() }, { maxAge: MoreThanOrEqual(age) }], | ||
]); | ||
const page = paginate(pagination); | ||
|
||
const result = await this.meetService.getMeets(where, page); | ||
return result.map(MeetResponseDto.of); | ||
} | ||
|
||
async getComment( | ||
@Get('/join') | ||
@UseGuards(JwtAuthGuard, RoleGuard(Role.USER)) | ||
@ApiOperation({ summary: '참여 완료 및 참여 상태인 모임 목록을 반환' }) | ||
@ApiBearerAuth() | ||
async getJoinedMeet( | ||
@AuthUser() user: AuthUserDto, | ||
@Query() payload: MeetCommentRequestDto, | ||
) { | ||
const { meetId } = payload; | ||
const result = await this.meetService.getComment(user, meetId); | ||
return result.map(MeetCommentResponseDto.of); | ||
@Query() payload: PaginationDto, | ||
): Promise<MeetResponseDto[]> { | ||
const { id: userId } = user; | ||
const { ...pagination } = payload; | ||
|
||
const where: FindOptionsWhere<Meet>[] = [ | ||
{ participations: { user: { id: userId } } }, | ||
{ host: { id: userId } }, | ||
]; | ||
const page = paginate(pagination); | ||
|
||
const result = await this.meetService.getMeets(where, page); | ||
return result.map(MeetResponseDto.of); | ||
} | ||
|
||
@Get('/:id') | ||
@UseGuards(JwtAuthGuard, RoleGuard(Role.USER)) | ||
@ApiOperation({ summary: '모임 상세 정보를 반환' }) | ||
@ApiBearerAuth() | ||
async getMeet( | ||
@Param() payload: MeetDetailRequestDto, | ||
): Promise<MeetDetailResponseDto> { | ||
const { id } = payload; | ||
|
||
const meet = await this.meetService.getMeetById(id); | ||
return MeetDetailResponseDto.of(meet); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
export class AuthUserDto { | ||
id: number; | ||
refreshToken: string; | ||
email: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { AuthUserDto } from './auth.user.dto'; | ||
import { PaginationDto } from './pagination.dto'; | ||
import { TokenPayloadDto } from './token.payload.dto'; | ||
|
||
export { AuthUserDto, TokenPayloadDto }; | ||
export { AuthUserDto, TokenPayloadDto, PaginationDto }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Type } from 'class-transformer'; | ||
import { IsNumber, IsOptional } from 'class-validator'; | ||
|
||
export class PaginationDto { | ||
@IsOptional() | ||
@IsNumber() | ||
@Type(() => Number) | ||
page?: number = 1; | ||
|
||
@IsOptional() | ||
@IsNumber() | ||
@Type(() => Number) | ||
size?: number = 10; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,15 @@ | ||
import { MeetResponseDto } from './meet.res.dto'; | ||
import { MeetGetRequestDto } from './meet.get.req.dto'; | ||
import { MeetRequestDto } from './meet.req.dto'; | ||
import { MeetCommentRequestDto } from './meet.comment.req.dto'; | ||
import { MeetCommentResponseDto } from './meet.comment.res.dto'; | ||
import { MeetDetailRequestDto } from './meet.detail.req.dto'; | ||
import { MeetDetailResponseDto } from './meet.detail.res.dto'; | ||
|
||
export { | ||
MeetResponseDto, | ||
MeetDetailResponseDto, | ||
MeetCommentRequestDto, | ||
MeetGetRequestDto, | ||
MeetRequestDto, | ||
MeetDetailRequestDto, | ||
MeetCommentResponseDto, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Transform } from 'class-transformer'; | ||
import { IsNumber } from 'class-validator'; | ||
|
||
export class MeetDetailRequestDto { | ||
@IsNumber() | ||
@Transform(({ value }) => parseInt(value)) | ||
id: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Meet } from 'src/entities'; | ||
import { MeetResponseDto } from './meet.res.dto'; | ||
import { Gender } from 'src/lib/enums'; | ||
import { UserResponseDto } from '../user'; | ||
|
||
export class MeetDetailResponseDto extends MeetResponseDto { | ||
body: string; | ||
maxParticipants: number; | ||
isOnline: boolean; | ||
location: string; | ||
minAge: number; | ||
maxAge: number; | ||
gender: Gender; | ||
createdAt: Date; | ||
participants: UserResponseDto[]; | ||
|
||
static of(meet: Meet): MeetDetailResponseDto { | ||
const { | ||
body, | ||
maxParticipants, | ||
isOnline, | ||
location, | ||
minAge, | ||
maxAge, | ||
gender, | ||
createdAt, | ||
participations, | ||
} = meet; | ||
return { | ||
...super.of(meet), | ||
body, | ||
maxParticipants, | ||
isOnline, | ||
location, | ||
minAge, | ||
maxAge, | ||
gender, | ||
createdAt, | ||
participants: participations | ||
.map((participation) => participation.user) | ||
.map(UserResponseDto.of), | ||
}; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Transform } from 'class-transformer'; | ||
import { IsBoolean, IsOptional } from 'class-validator'; | ||
import { PaginationDto } from '../common'; | ||
|
||
export class MeetRequestDto extends PaginationDto { | ||
@IsBoolean() | ||
@IsOptional() | ||
@Transform(({ value }) => value === 'true' || value === true) | ||
subscribed?: boolean = false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,23 @@ | ||
import { Meet } from 'src/entities'; | ||
import { Gender } from 'src/lib/enums'; | ||
import { TagResponseDto } from '../tag'; | ||
import { UserResponseDto } from '../user'; | ||
|
||
export class MeetResponseDto { | ||
id: number; | ||
hostId: number; | ||
host: UserResponseDto; | ||
title: string; | ||
body: string; | ||
maxParticipants: number; | ||
meetTime: Date; | ||
isOnline: boolean; | ||
location: string; | ||
minAge: number; | ||
maxAge: number; | ||
gender: Gender; | ||
createdAt: Date; | ||
tagId: number; | ||
tag: TagResponseDto; | ||
|
||
static of(meet: Meet): MeetResponseDto { | ||
const { | ||
id, | ||
hostId, | ||
title, | ||
body, | ||
maxParticipants, | ||
meetTime, | ||
isOnline, | ||
location, | ||
minAge, | ||
maxAge, | ||
gender, | ||
createdAt, | ||
tagId, | ||
} = meet; | ||
const { id, host, title, meetTime, tag } = meet; | ||
|
||
return { | ||
id, | ||
hostId, | ||
host: UserResponseDto.of(host), | ||
title, | ||
body, | ||
maxParticipants, | ||
meetTime, | ||
isOnline, | ||
location, | ||
minAge, | ||
maxAge, | ||
gender, | ||
createdAt, | ||
tagId, | ||
tag: TagResponseDto.of(tag), | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const productArray = <T>(array: T[][]): T[] => | ||
array.reduce((acc, cur) => { | ||
return acc.length | ||
? acc.map((a) => cur.map((c) => ({ ...a, ...c }))).flat() | ||
: cur; | ||
}, []); | ||
|
||
export { productArray }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { PaginationDto } from 'src/dtos/common/pagination.dto'; | ||
import { FindManyOptions } from 'typeorm'; | ||
|
||
type FindOptionsPage = Pick<FindManyOptions, 'skip' | 'take'>; | ||
|
||
const paginate = ({ page, size }: PaginationDto): FindOptionsPage => ({ | ||
skip: (page - 1) * size, | ||
take: size, | ||
}); | ||
|
||
export { FindOptionsPage, paginate }; |