Skip to content

Commit cba4487

Browse files
authored
Merge branch 'dev' into feat/2
2 parents 53fa387 + e1bc7b6 commit cba4487

File tree

21 files changed

+388
-5
lines changed

21 files changed

+388
-5
lines changed

backend/.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@ out/
4040
.env
4141

4242
### .idea ###
43-
.idea
43+
.idea
44+
45+
### images/thumbnail ###
46+
images/thumbnail/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.f1.backend.domain.question.app;
2+
3+
import static io.f1.backend.domain.question.mapper.QuestionMapper.questionRequestToQuestion;
4+
import static io.f1.backend.domain.question.mapper.TextQuestionMapper.questionRequestToTextQuestion;
5+
6+
import io.f1.backend.domain.question.dao.QuestionRepository;
7+
import io.f1.backend.domain.question.dao.TextQuestionRepository;
8+
import io.f1.backend.domain.question.dto.QuestionRequest;
9+
import io.f1.backend.domain.question.entity.Question;
10+
import io.f1.backend.domain.question.entity.TextQuestion;
11+
import io.f1.backend.domain.quiz.entity.Quiz;
12+
13+
import lombok.RequiredArgsConstructor;
14+
15+
import org.springframework.stereotype.Service;
16+
import org.springframework.transaction.annotation.Transactional;
17+
18+
@Service
19+
@RequiredArgsConstructor
20+
public class QuestionService {
21+
22+
private final QuestionRepository questionRepository;
23+
private final TextQuestionRepository textQuestionRepository;
24+
25+
@Transactional
26+
public void saveQuestion(Quiz quiz, QuestionRequest request) {
27+
28+
Question question = questionRequestToQuestion(quiz, request);
29+
quiz.addQuestion(question);
30+
questionRepository.save(question);
31+
32+
TextQuestion textQuestion = questionRequestToTextQuestion(question, request.getContent());
33+
textQuestionRepository.save(textQuestion);
34+
question.addTextQuestion(textQuestion);
35+
}
36+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.f1.backend.domain.question.dao;
2+
3+
import io.f1.backend.domain.question.entity.Question;
4+
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
7+
public interface QuestionRepository extends JpaRepository<Question, Long> {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.f1.backend.domain.question.dao;
2+
3+
import io.f1.backend.domain.question.entity.TextQuestion;
4+
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
7+
public interface TextQuestionRepository extends JpaRepository<TextQuestion, Long> {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.f1.backend.domain.question.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
5+
import lombok.AccessLevel;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
@Getter
10+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
11+
public class QuestionRequest {
12+
13+
@NotBlank(message = "문제를 입력해주세요.")
14+
private String content;
15+
16+
@NotBlank(message = "정답을 입력해주세요.")
17+
private String answer;
18+
}

backend/src/main/java/io/f1/backend/domain/question/entity/Question.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
import jakarta.persistence.ManyToOne;
1515
import jakarta.persistence.OneToOne;
1616

17+
import lombok.AccessLevel;
18+
import lombok.NoArgsConstructor;
19+
1720
@Entity
21+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
1822
public class Question extends BaseEntity {
1923

2024
@Id
@@ -30,4 +34,13 @@ public class Question extends BaseEntity {
3034

3135
@OneToOne(mappedBy = "question", cascade = CascadeType.REMOVE)
3236
private TextQuestion textQuestion;
37+
38+
public Question(Quiz quiz, String answer) {
39+
this.quiz = quiz;
40+
this.answer = answer;
41+
}
42+
43+
public void addTextQuestion(TextQuestion textQuestion) {
44+
this.textQuestion = textQuestion;
45+
}
3346
}

backend/src/main/java/io/f1/backend/domain/question/entity/TextQuestion.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
import jakarta.persistence.JoinColumn;
99
import jakarta.persistence.OneToOne;
1010

11+
import lombok.AccessLevel;
12+
import lombok.NoArgsConstructor;
13+
1114
@Entity
15+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
1216
public class TextQuestion {
1317

1418
@Id
@@ -21,4 +25,9 @@ public class TextQuestion {
2125

2226
@Column(nullable = false)
2327
private String content;
28+
29+
public TextQuestion(Question question, String content) {
30+
this.question = question;
31+
this.content = content;
32+
}
2433
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.f1.backend.domain.question.mapper;
2+
3+
import io.f1.backend.domain.question.dto.QuestionRequest;
4+
import io.f1.backend.domain.question.entity.Question;
5+
import io.f1.backend.domain.quiz.entity.Quiz;
6+
7+
public class QuestionMapper {
8+
9+
public static Question questionRequestToQuestion(Quiz quiz, QuestionRequest questionRequest) {
10+
return new Question(quiz, questionRequest.getAnswer());
11+
}
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.f1.backend.domain.question.mapper;
2+
3+
import io.f1.backend.domain.question.entity.Question;
4+
import io.f1.backend.domain.question.entity.TextQuestion;
5+
6+
public class TextQuestionMapper {
7+
8+
public static TextQuestion questionRequestToTextQuestion(Question question, String content) {
9+
return new TextQuestion(question, content);
10+
}
11+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.f1.backend.domain.quiz.api;
2+
3+
import io.f1.backend.domain.quiz.app.QuizService;
4+
import io.f1.backend.domain.quiz.dto.QuizCreateRequest;
5+
import io.f1.backend.domain.quiz.dto.QuizCreateResponse;
6+
7+
import jakarta.validation.Valid;
8+
9+
import lombok.RequiredArgsConstructor;
10+
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.http.MediaType;
13+
import org.springframework.http.ResponseEntity;
14+
import org.springframework.web.bind.annotation.PostMapping;
15+
import org.springframework.web.bind.annotation.RequestMapping;
16+
import org.springframework.web.bind.annotation.RequestPart;
17+
import org.springframework.web.bind.annotation.RestController;
18+
import org.springframework.web.multipart.MultipartFile;
19+
20+
import java.io.IOException;
21+
22+
@RestController
23+
@RequestMapping("/quizzes")
24+
@RequiredArgsConstructor
25+
public class QuizController {
26+
27+
private final QuizService quizService;
28+
29+
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
30+
public ResponseEntity<QuizCreateResponse> saveQuiz(
31+
@RequestPart(required = false) MultipartFile thumbnailFile,
32+
@Valid @RequestPart QuizCreateRequest request)
33+
throws IOException {
34+
QuizCreateResponse response = quizService.saveQuiz(thumbnailFile, request);
35+
36+
return ResponseEntity.status(HttpStatus.CREATED).body(response);
37+
}
38+
}

0 commit comments

Comments
 (0)