diff --git a/src/user/dto/reqeust/question-request.dto.ts b/src/user/dto/reqeust/question-request.dto.ts new file mode 100644 index 0000000..c6c5192 --- /dev/null +++ b/src/user/dto/reqeust/question-request.dto.ts @@ -0,0 +1,20 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsByteLength, IsNotEmpty, IsString } from 'class-validator'; + +export class QuestionRequest { + @ApiProperty({ description: '문의 제목' }) + @IsString() + @IsNotEmpty({ message: '제목은 필수입니다.' }) + readonly title: string; + + @ApiProperty({ description: '답변 받을 이메일' }) + @IsString() + @IsNotEmpty({ message: '이메일은 필수입니다.' }) + readonly email: string; + + @ApiProperty({ description: '문의 내용' }) + @IsString() + @IsNotEmpty({ message: '문의 내용은 필수입니다.' }) + @IsByteLength(20, 10000, { message: '문의 내용은 10글자 이상이어야 합니다.' }) + readonly contents: string; +} diff --git a/src/user/dto/response/question-response.dto.ts b/src/user/dto/response/question-response.dto.ts new file mode 100644 index 0000000..48fee16 --- /dev/null +++ b/src/user/dto/response/question-response.dto.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class QuestionResponse { + @ApiProperty({ description: '문의 전송 여부', example: true }) + isSended: boolean; +} diff --git a/src/user/entity/question.entity.ts b/src/user/entity/question.entity.ts new file mode 100644 index 0000000..4eefc1d --- /dev/null +++ b/src/user/entity/question.entity.ts @@ -0,0 +1,17 @@ +import { BaseEntity } from 'src/global/base/base.entity'; +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity('questions') +export class Question extends BaseEntity { + @PrimaryGeneratedColumn() + questionId: number; + + @Column() + title: string; + + @Column() + reporter: string; + + @Column() + contents: string; +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 8c56937..244d86e 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -32,6 +32,8 @@ import { ReportUserResponse } from './dto/response/report-user-response.dto'; import { SignUpResponse } from './dto/response/sign-up-response.dto'; import { UserConverter } from './user.converter'; import { UserService } from './user.service'; +import { QuestionResponse } from './dto/response/question-response.dto'; +import { QuestionRequest } from './dto/reqeust/question-request.dto'; @Controller('api/users') @ApiTags('users') @@ -105,4 +107,16 @@ export class UserController { GlobalResponseCode.OK, ); } + + @Post('question') + @UseGuards(JwtAuthGuard) + @ApiOperation({ + summary: '문의 API', + }) + @ApiBearerAuth() + @ApiCreatedResponse({ type: QuestionResponse, description: '문의 전송 성공' }) + async question(@Body() request: QuestionRequest): Promise> { + const question = await this.userService.question(request); + return BaseResponse.of(UserConverter.toQuestionResponse(question)); + } } diff --git a/src/user/user.converter.ts b/src/user/user.converter.ts index d9e6885..217783e 100644 --- a/src/user/user.converter.ts +++ b/src/user/user.converter.ts @@ -10,6 +10,8 @@ import { Password } from './entity/password'; import { UserReport } from './entity/user-report.entity'; import { User } from './entity/user.entity'; import { UserReportReason } from './enum/user-report-reason'; +import { QuestionResponse } from './dto/response/question-response.dto'; +import { Question } from './entity/question.entity'; @Injectable() export class UserConverter implements OnModuleInit { @@ -57,4 +59,10 @@ export class UserConverter implements OnModuleInit { public static toFindingPasswordResponse(isPasswordSended: boolean): FindingPasswordResponse { return Builder(FindingPasswordResponse).isPasswordSended(isPasswordSended).build(); } + + public static toQuestionResponse(question: Question): QuestionResponse { + return Builder(QuestionResponse) + .isSended(question ? true : false) + .build(); + } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 931a8d3..45ce348 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -11,6 +11,8 @@ import { UserReport } from './entity/user-report.entity'; import { User } from './entity/user.entity'; import { UserResponseCode } from './exception/user-response-code'; import { UserConverter } from './user.converter'; +import { QuestionRequest } from './dto/reqeust/question-request.dto'; +import { Question } from './entity/question.entity'; @Injectable() export class UserService { @@ -22,6 +24,8 @@ export class UserService { @InjectRepository(UserReport) private readonly userReportRepository: Repository, private readonly mailService: MailService, + @InjectRepository(Question) + private readonly questionRepository: Repository, ) {} async isUserExists(userId: number): Promise { @@ -87,4 +91,8 @@ export class UserService { async sendEmail(request: FindingPasswordRequest, password: string): Promise { await this.mailService.sendMail(request.email, '[BookJam] 임시 비밀번호 안내', password); } + + async question(request: QuestionRequest) { + return await this.questionRepository.save(request); + } }