From db43082dd8fe81efdda23b8b06a5a5e0f6e46fbb Mon Sep 17 00:00:00 2001 From: HeeJun Yoon Date: Tue, 11 Feb 2025 22:35:17 +0900 Subject: [PATCH 1/8] :sparkles:Feat: Update issue templates --- ".github/ISSUE_TEMPLATE/\342\234\250-feature.md" | 2 +- ".github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" | 2 +- ".github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git "a/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" "b/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" index 07d5fd2..e9384c6 100644 --- "a/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" +++ "b/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" @@ -2,7 +2,7 @@ name: "✨ Feature" about: 기능 추가 이슈 템플릿 title: "✨Feat: " -labels: enhancement +labels: '' assignees: '' --- diff --git "a/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" "b/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" index d0b3059..9edbf0c 100644 --- "a/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" +++ "b/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" @@ -2,7 +2,7 @@ name: "\U0001F41B Fix" about: 버그 및 에러 이슈 템플릿 title: "\U0001F41BFix: " -labels: bug +labels: '' assignees: '' --- diff --git "a/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" "b/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" index 314db28..08e7fd3 100644 --- "a/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" +++ "b/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" @@ -2,7 +2,7 @@ name: "\U0001F4DD Documentation" about: 문서 수정 이슈 템플릿 title: "\U0001F4DDDocs: " -labels: documentation +labels: '' assignees: '' --- From 548cedf9987fc16f1060d04b392279a0183d1cce Mon Sep 17 00:00:00 2001 From: HeeJun Yoon Date: Tue, 11 Feb 2025 22:39:03 +0900 Subject: [PATCH 2/8] :sparkles:Feat: Update issue templates --- ".github/ISSUE_TEMPLATE/\342\231\273\357\270\217-refactor.md" | 2 +- ".github/ISSUE_TEMPLATE/\342\234\250-feature.md" | 2 +- ".github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" | 2 +- ".github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git "a/.github/ISSUE_TEMPLATE/\342\231\273\357\270\217-refactor.md" "b/.github/ISSUE_TEMPLATE/\342\231\273\357\270\217-refactor.md" index cbbafba..093496e 100644 --- "a/.github/ISSUE_TEMPLATE/\342\231\273\357\270\217-refactor.md" +++ "b/.github/ISSUE_TEMPLATE/\342\231\273\357\270\217-refactor.md" @@ -2,7 +2,7 @@ name: "♻️ Refactor" about: 리팩토링 이슈 템플릿 title: "♻️Refactor: " -labels: '' +labels: ":recycle: Refactor" assignees: '' --- diff --git "a/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" "b/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" index e9384c6..aa13c26 100644 --- "a/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" +++ "b/.github/ISSUE_TEMPLATE/\342\234\250-feature.md" @@ -2,7 +2,7 @@ name: "✨ Feature" about: 기능 추가 이슈 템플릿 title: "✨Feat: " -labels: '' +labels: "✨ Feature" assignees: '' --- diff --git "a/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" "b/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" index 9edbf0c..b9141c3 100644 --- "a/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" +++ "b/.github/ISSUE_TEMPLATE/\360\237\220\233-fix.md" @@ -2,7 +2,7 @@ name: "\U0001F41B Fix" about: 버그 및 에러 이슈 템플릿 title: "\U0001F41BFix: " -labels: '' +labels: "\U0001F41E BugFix" assignees: '' --- diff --git "a/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" "b/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" index 08e7fd3..07edba1 100644 --- "a/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" +++ "b/.github/ISSUE_TEMPLATE/\360\237\223\235-documentation.md" @@ -2,7 +2,7 @@ name: "\U0001F4DD Documentation" about: 문서 수정 이슈 템플릿 title: "\U0001F4DDDocs: " -labels: '' +labels: "\U0001F4C3 Docs" assignees: '' --- From 2eb46d09cdb9bb2e9e7b3ca22a828c14fa4d8d16 Mon Sep 17 00:00:00 2001 From: HeeJun Yoon Date: Thu, 20 Feb 2025 23:58:39 +0900 Subject: [PATCH 3/8] =?UTF-8?q?:rocket:=20gradle.yml=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 46dc506..75ab1a9 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -87,7 +87,7 @@ jobs: # 3. 최신 이미지를 컨테이너화하여 실행 - name: docker run new container - run: sudo docker run --name helfoome --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/trendithon + run: sudo docker run --name trendithon --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/trendithon # 4. 미사용 이미지를 정리 - name: delete old docker image From f0f56ee79d9b38ec4d413d1b136a603d389ddba1 Mon Sep 17 00:00:00 2001 From: HeeJun Yoon Date: Fri, 21 Feb 2025 00:00:55 +0900 Subject: [PATCH 4/8] =?UTF-8?q?:rocket:=20gradle.yml=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 75ab1a9..46dc506 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -87,7 +87,7 @@ jobs: # 3. 최신 이미지를 컨테이너화하여 실행 - name: docker run new container - run: sudo docker run --name trendithon --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/trendithon + run: sudo docker run --name helfoome --rm -d -p 8080:8080 -e TZ=Asia/Seoul ${{ secrets.DOCKERHUB_USERNAME }}/trendithon # 4. 미사용 이미지를 정리 - name: delete old docker image From 4006f06e0ce27cdb7ca43d0e6db42fee98ec1af1 Mon Sep 17 00:00:00 2001 From: rkddpfls02 Date: Fri, 21 Feb 2025 01:38:59 +0900 Subject: [PATCH 5/8] =?UTF-8?q?:sparkles:Feat:=20Card,=20Tag=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../likelion/trendithon/domain/card/Card.java | 31 +++++++ .../domain/card/CardController.java | 92 +++++++++++++++++++ .../domain/card/CardRepository.java | 7 ++ .../domain/card/CardResponseDto.java | 18 ++++ .../trendithon/domain/card/CardService.java | 70 ++++++++++++++ .../likelion/trendithon/domain/tag/Tag.java | 33 +++++++ .../trendithon/domain/tag/TagRepository.java | 10 ++ .../trendithon/domain/tag/TagService.java | 54 +++++++++++ 8 files changed, 315 insertions(+) create mode 100644 src/main/java/com/likelion/trendithon/domain/card/Card.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardController.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardRepository.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardService.java create mode 100644 src/main/java/com/likelion/trendithon/domain/tag/Tag.java create mode 100644 src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java create mode 100644 src/main/java/com/likelion/trendithon/domain/tag/TagService.java diff --git a/src/main/java/com/likelion/trendithon/domain/card/Card.java b/src/main/java/com/likelion/trendithon/domain/card/Card.java new file mode 100644 index 0000000..43a5200 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/Card.java @@ -0,0 +1,31 @@ +package com.likelion.trendithon.domain.card; + +import com.likelion.trendithon.domain.tag.Tag; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import java.util.*; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class Card { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long cardId; + + private String title; + + private String content; + + private String imgUrl; + + @OneToMany(mappedBy = "Tag", cascade = CascadeType.ALL, orphanRemoval = true) + private List TagItems = new ArrayList<>(); +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardController.java b/src/main/java/com/likelion/trendithon/domain/card/CardController.java new file mode 100644 index 0000000..a91b4c6 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/CardController.java @@ -0,0 +1,92 @@ +package com.likelion.trendithon.domain.card; + +import java.util.*; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@AllArgsConstructor +@RequestMapping("/api/cards") +public class CardController { + + private CardService cardService; + + @PostMapping("/create") + public ResponseEntity> createCard(@RequestBody Card card) { + try { + Card result = cardService.createCard(card); + + Map response = new HashMap<>(); + response.put("message", "Card "); + response.put("card", result); + + return ResponseEntity.status(HttpStatus.CREATED).body(response); + } catch (Exception e) { + + Map errorResponse = new HashMap<>(); + errorResponse.put("message", "Error ߻"); + errorResponse.put("error", e.getMessage()); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); + } + } + + @GetMapping("/{id}") + public ResponseEntity getCardById(@PathVariable Long id) { + try { + Card card = cardService.getCardById(id); + if (card == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("ش Card "); + } + return ResponseEntity.ok(card); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error ߻"); + } + } + + @GetMapping() + public ResponseEntity getAllCards() { + try { + List cards = cardService.getAllCards(); + if (cards.isEmpty()) { + return ResponseEntity.status(HttpStatus.NO_CONTENT).body("ī尡 "); + } + return ResponseEntity.ok(cards); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error ߻"); + } + } + + @DeleteMapping("/{id}") + public ResponseEntity> deleteCard(@PathVariable Long id) { + cardService.deleteCard(id); + + Map response = new HashMap<>(); + response.put("message", "Card Ϸ"); + + return ResponseEntity.ok(response); + } + + @PostMapping("/update/{id}") + public ResponseEntity updateCard(@PathVariable Long id, @RequestBody Card updatedCard) { + Card newCard = cardService.updateCard(id, updatedCard); + + if (newCard == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("ī尡 "); + } else { + return ResponseEntity.ok(newCard); + } + } + + + + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java b/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java new file mode 100644 index 0000000..18f5f14 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java @@ -0,0 +1,7 @@ +package com.likelion.trendithon.domain.card; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CardRepository extends JpaRepository { + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java b/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java new file mode 100644 index 0000000..9867d9b --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java @@ -0,0 +1,18 @@ +package com.likelion.trendithon.domain.card; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CardResponseDto { + + private Long cardId; + private String title; + + public CardResponseDto(Long id, String title) { + this.cardId = id; + this.title = title; + } + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardService.java b/src/main/java/com/likelion/trendithon/domain/card/CardService.java new file mode 100644 index 0000000..2ebe6ad --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/CardService.java @@ -0,0 +1,70 @@ +package com.likelion.trendithon.domain.card; + +import com.likelion.trendithon.domain.tag.Tag; +import com.likelion.trendithon.domain.tag.TagService; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +public class CardService { + + private CardRepository cardRepository; + private TagService tagService; + + public Card createCard(Card card) { + List tags= card.getTagItems(); + tagService.createTag(tags); + return cardRepository.save(card); + } + + public Card getCardById(Long id) { + Optional optionalCard= cardRepository.findById(id); + Card card; + if(optionalCard.isPresent()) { + card= optionalCard.get(); + card.setTagItems(tagService.getTags(card)); + return card; + } + + return null; + } + + public List getAllCards() { + List cardList= cardRepository.findAll(); + List cardDtos = new ArrayList<>(); + + for (Card card : cardList) { + cardDtos.add(new CardResponseDto(card.getCardId(), card.getTitle())); + } + + return cardDtos; + + } + + public void deleteCard(Long id) { + Optional optionalCard= cardRepository.findById(id); + optionalCard.ifPresent(card -> cardRepository.delete(card)); + } + + public Card updateCard(Long id, Card updatedCard) { + Optional optionalCard= cardRepository.findById(id); + Card newCard; + if(optionalCard.isPresent()){ + newCard= optionalCard.get(); + List newTags= tagService.updateTags(newCard); + + newCard.setTagItems(newTags); + newCard.setContent(updatedCard.getContent()); + newCard.setTitle(updatedCard.getTitle()); + newCard.setImgUrl(updatedCard.getImgUrl()); + + return cardRepository.save(newCard); + } + + else return null; + } +} diff --git a/src/main/java/com/likelion/trendithon/domain/tag/Tag.java b/src/main/java/com/likelion/trendithon/domain/tag/Tag.java new file mode 100644 index 0000000..dbf8517 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/tag/Tag.java @@ -0,0 +1,33 @@ +package com.likelion.trendithon.domain.tag; + +import com.likelion.trendithon.domain.card.Card; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class Tag { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long tagId; + + @Column + private String tagTitle; + + private String tagContent; + + @ManyToOne + @JoinColumn(name = "card_id", nullable = false) + private Card card; + + +} diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java b/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java new file mode 100644 index 0000000..52ddbc5 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java @@ -0,0 +1,10 @@ +package com.likelion.trendithon.domain.tag; + +import com.likelion.trendithon.domain.card.Card; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TagRepository extends JpaRepository { + + List findByCard(Card card); +} diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagService.java b/src/main/java/com/likelion/trendithon/domain/tag/TagService.java new file mode 100644 index 0000000..dd4ea93 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/tag/TagService.java @@ -0,0 +1,54 @@ +package com.likelion.trendithon.domain.tag; + +import com.likelion.trendithon.domain.card.Card; +import java.util.List; +import java.util.Objects; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +public class TagService { + + private TagRepository tagRepository; + + public void createTag(List tags){ + tagRepository.saveAll(tags); + } + + public List getTags(Card card){ + return tagRepository.findByCard(card); + } + + public List updateTags(Card card) { + + List tags = tagRepository.findByCard(card); + List newTags = card.getTagItems(); + + // tags ϴµ newTags + for (Tag tag : tags) { + for (Tag newTag : newTags) { + if (Objects.equals(tag.getTagId(), newTag.getTagId())) { + tag.setTagTitle(newTag.getTagTitle()); + tag.setTagContent(newTag.getTagContent()); + break; + } + } + + tags.remove(tag); + tagRepository.delete(tag); + } + + // newTags ϴµ tags ߰ + for (Tag newTag : newTags) { + for (Tag tag : tags){ + if (Objects.equals(tag.getTagId(), newTag.getTagId())) break; + } + + tags.add(newTag); + tagRepository.save(newTag); + } + + return tags; + } +} \ No newline at end of file From 37a44264ff320dc56d9282a037479b684633ef10 Mon Sep 17 00:00:00 2001 From: rkddpfls02 Date: Fri, 21 Feb 2025 02:02:20 +0900 Subject: [PATCH 6/8] =?UTF-8?q?:sparkles:Feat:=20Card,=20Tag=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../likelion/trendithon/domain/card/Card.java | 9 +++-- .../domain/card/CardController.java | 24 ++++++------- .../domain/card/CardRepository.java | 4 +-- .../domain/card/CardResponseDto.java | 1 - .../trendithon/domain/card/CardService.java | 34 +++++++++---------- .../likelion/trendithon/domain/tag/Tag.java | 9 +++-- .../trendithon/domain/tag/TagRepository.java | 4 ++- .../trendithon/domain/tag/TagService.java | 19 ++++++----- 8 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/likelion/trendithon/domain/card/Card.java b/src/main/java/com/likelion/trendithon/domain/card/Card.java index 43a5200..08fadd6 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/Card.java +++ b/src/main/java/com/likelion/trendithon/domain/card/Card.java @@ -1,13 +1,16 @@ package com.likelion.trendithon.domain.card; -import com.likelion.trendithon.domain.tag.Tag; +import java.util.*; + import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import java.util.*; + +import com.likelion.trendithon.domain.tag.Tag; + import lombok.Getter; import lombok.Setter; @@ -26,6 +29,6 @@ public class Card { private String imgUrl; - @OneToMany(mappedBy = "Tag", cascade = CascadeType.ALL, orphanRemoval = true) + @OneToMany(mappedBy = "card", cascade = CascadeType.ALL, orphanRemoval = true) private List TagItems = new ArrayList<>(); } diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardController.java b/src/main/java/com/likelion/trendithon/domain/card/CardController.java index a91b4c6..e3e9f4f 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/CardController.java +++ b/src/main/java/com/likelion/trendithon/domain/card/CardController.java @@ -1,7 +1,7 @@ package com.likelion.trendithon.domain.card; import java.util.*; -import lombok.AllArgsConstructor; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -12,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import lombok.AllArgsConstructor; + @Controller @AllArgsConstructor @RequestMapping("/api/cards") @@ -25,14 +27,14 @@ public ResponseEntity> createCard(@RequestBody Card card) { Card result = cardService.createCard(card); Map response = new HashMap<>(); - response.put("message", "Card "); + response.put("message", "Card 생성 성공"); response.put("card", result); return ResponseEntity.status(HttpStatus.CREATED).body(response); } catch (Exception e) { Map errorResponse = new HashMap<>(); - errorResponse.put("message", "Error ߻"); + errorResponse.put("message", "Error 발생"); errorResponse.put("error", e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); @@ -44,11 +46,11 @@ public ResponseEntity getCardById(@PathVariable Long id) { try { Card card = cardService.getCardById(id); if (card == null) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("ش Card "); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("해당 Card가 존재하지 않음"); } return ResponseEntity.ok(card); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error ߻"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error 발생"); } } @@ -57,11 +59,11 @@ public ResponseEntity getAllCards() { try { List cards = cardService.getAllCards(); if (cards.isEmpty()) { - return ResponseEntity.status(HttpStatus.NO_CONTENT).body("ī尡 "); + return ResponseEntity.status(HttpStatus.NO_CONTENT).body("카드가 존재하지 않음"); } return ResponseEntity.ok(cards); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error ߻"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error 발생"); } } @@ -70,7 +72,7 @@ public ResponseEntity> deleteCard(@PathVariable Long id) { cardService.deleteCard(id); Map response = new HashMap<>(); - response.put("message", "Card Ϸ"); + response.put("message", "Card 삭제 완료"); return ResponseEntity.ok(response); } @@ -80,13 +82,9 @@ public ResponseEntity updateCard(@PathVariable Long id, @RequestBody Card upd Card newCard = cardService.updateCard(id, updatedCard); if (newCard == null) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("ī尡 "); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("카드가 존재하지 않음"); } else { return ResponseEntity.ok(newCard); } } - - - - } diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java b/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java index 18f5f14..741e648 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java +++ b/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java @@ -2,6 +2,4 @@ import org.springframework.data.jpa.repository.JpaRepository; -public interface CardRepository extends JpaRepository { - -} +public interface CardRepository extends JpaRepository {} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java b/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java index 9867d9b..aee995c 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java +++ b/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java @@ -14,5 +14,4 @@ public CardResponseDto(Long id, String title) { this.cardId = id; this.title = title; } - } diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardService.java b/src/main/java/com/likelion/trendithon/domain/card/CardService.java index 2ebe6ad..01ea6f6 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/CardService.java +++ b/src/main/java/com/likelion/trendithon/domain/card/CardService.java @@ -1,13 +1,16 @@ package com.likelion.trendithon.domain.card; -import com.likelion.trendithon.domain.tag.Tag; -import com.likelion.trendithon.domain.tag.TagService; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import lombok.AllArgsConstructor; + import org.springframework.stereotype.Service; +import com.likelion.trendithon.domain.tag.Tag; +import com.likelion.trendithon.domain.tag.TagService; + +import lombok.AllArgsConstructor; + @Service @AllArgsConstructor public class CardService { @@ -16,16 +19,16 @@ public class CardService { private TagService tagService; public Card createCard(Card card) { - List tags= card.getTagItems(); + List tags = card.getTagItems(); tagService.createTag(tags); return cardRepository.save(card); } public Card getCardById(Long id) { - Optional optionalCard= cardRepository.findById(id); + Optional optionalCard = cardRepository.findById(id); Card card; - if(optionalCard.isPresent()) { - card= optionalCard.get(); + if (optionalCard.isPresent()) { + card = optionalCard.get(); card.setTagItems(tagService.getTags(card)); return card; } @@ -34,7 +37,7 @@ public Card getCardById(Long id) { } public List getAllCards() { - List cardList= cardRepository.findAll(); + List cardList = cardRepository.findAll(); List cardDtos = new ArrayList<>(); for (Card card : cardList) { @@ -42,20 +45,19 @@ public List getAllCards() { } return cardDtos; - } public void deleteCard(Long id) { - Optional optionalCard= cardRepository.findById(id); + Optional optionalCard = cardRepository.findById(id); optionalCard.ifPresent(card -> cardRepository.delete(card)); } public Card updateCard(Long id, Card updatedCard) { - Optional optionalCard= cardRepository.findById(id); + Optional optionalCard = cardRepository.findById(id); Card newCard; - if(optionalCard.isPresent()){ - newCard= optionalCard.get(); - List newTags= tagService.updateTags(newCard); + if (optionalCard.isPresent()) { + newCard = optionalCard.get(); + List newTags = tagService.updateTags(newCard); newCard.setTagItems(newTags); newCard.setContent(updatedCard.getContent()); @@ -63,8 +65,6 @@ public Card updateCard(Long id, Card updatedCard) { newCard.setImgUrl(updatedCard.getImgUrl()); return cardRepository.save(newCard); - } - - else return null; + } else return null; } } diff --git a/src/main/java/com/likelion/trendithon/domain/tag/Tag.java b/src/main/java/com/likelion/trendithon/domain/tag/Tag.java index dbf8517..5235077 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/Tag.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/Tag.java @@ -1,6 +1,5 @@ package com.likelion.trendithon.domain.tag; -import com.likelion.trendithon.domain.card.Card; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -8,6 +7,9 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; + +import com.likelion.trendithon.domain.card.Card; + import lombok.Getter; import lombok.Setter; @@ -20,14 +22,11 @@ public class Tag { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long tagId; - @Column - private String tagTitle; + @Column private String tagTitle; private String tagContent; @ManyToOne @JoinColumn(name = "card_id", nullable = false) private Card card; - - } diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java b/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java index 52ddbc5..e54022c 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java @@ -1,9 +1,11 @@ package com.likelion.trendithon.domain.tag; -import com.likelion.trendithon.domain.card.Card; import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import com.likelion.trendithon.domain.card.Card; + public interface TagRepository extends JpaRepository { List findByCard(Card card); diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagService.java b/src/main/java/com/likelion/trendithon/domain/tag/TagService.java index dd4ea93..119d911 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/TagService.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/TagService.java @@ -1,22 +1,25 @@ package com.likelion.trendithon.domain.tag; -import com.likelion.trendithon.domain.card.Card; import java.util.List; import java.util.Objects; -import lombok.AllArgsConstructor; + import org.springframework.stereotype.Service; +import com.likelion.trendithon.domain.card.Card; + +import lombok.AllArgsConstructor; + @Service @AllArgsConstructor public class TagService { private TagRepository tagRepository; - public void createTag(List tags){ + public void createTag(List tags) { tagRepository.saveAll(tags); } - public List getTags(Card card){ + public List getTags(Card card) { return tagRepository.findByCard(card); } @@ -25,7 +28,7 @@ public List updateTags(Card card) { List tags = tagRepository.findByCard(card); List newTags = card.getTagItems(); - // tags ϴµ newTags + // tags엔 존재하는데 newTags에 존재하지 않으면 삭제 같으면 업뎃 for (Tag tag : tags) { for (Tag newTag : newTags) { if (Objects.equals(tag.getTagId(), newTag.getTagId())) { @@ -39,9 +42,9 @@ public List updateTags(Card card) { tagRepository.delete(tag); } - // newTags ϴµ tags ߰ + // newTags엔 존재하는데 tags엔 존재하지 않으면 추가 for (Tag newTag : newTags) { - for (Tag tag : tags){ + for (Tag tag : tags) { if (Objects.equals(tag.getTagId(), newTag.getTagId())) break; } @@ -51,4 +54,4 @@ public List updateTags(Card card) { return tags; } -} \ No newline at end of file +} From f5daca0870e27e5f413fe960a5fa84a0abbd10cb Mon Sep 17 00:00:00 2001 From: rkddpfls02 Date: Fri, 21 Feb 2025 23:04:05 +0900 Subject: [PATCH 7/8] =?UTF-8?q?:sparkles:Feat:=20Card,=20Tag=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/card/CardController.java | 90 ------------ .../domain/card/CardRepository.java | 5 - .../domain/card/CardResponseDto.java | 17 --- .../trendithon/domain/card/CardService.java | 70 --------- .../card/controller/CardController.java | 57 ++++++++ .../domain/card/dto/CardListResponse.java | 22 +++ .../domain/card/dto/CardListSummaryDto.java | 23 +++ .../domain/card/dto/CardResponse.java | 23 +++ .../domain/card/dto/CardUpdateDto.java | 31 ++++ .../domain/card/{ => entity}/Card.java | 17 ++- .../card/repository/CardRepository.java | 9 ++ .../domain/card/service/CardService.java | 136 ++++++++++++++++++ .../domain/tag/{ => Service}/TagService.java | 12 +- .../domain/tag/{ => entity}/Tag.java | 14 +- .../tag/{ => repository}/TagRepository.java | 5 +- 15 files changed, 340 insertions(+), 191 deletions(-) delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardController.java delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardRepository.java delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/CardService.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java rename src/main/java/com/likelion/trendithon/domain/card/{ => entity}/Card.java (57%) create mode 100644 src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/service/CardService.java rename src/main/java/com/likelion/trendithon/domain/tag/{ => Service}/TagService.java (78%) rename src/main/java/com/likelion/trendithon/domain/tag/{ => entity}/Tag.java (60%) rename src/main/java/com/likelion/trendithon/domain/tag/{ => repository}/TagRepository.java (53%) diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardController.java b/src/main/java/com/likelion/trendithon/domain/card/CardController.java deleted file mode 100644 index e3e9f4f..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/CardController.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.likelion.trendithon.domain.card; - -import java.util.*; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; - -import lombok.AllArgsConstructor; - -@Controller -@AllArgsConstructor -@RequestMapping("/api/cards") -public class CardController { - - private CardService cardService; - - @PostMapping("/create") - public ResponseEntity> createCard(@RequestBody Card card) { - try { - Card result = cardService.createCard(card); - - Map response = new HashMap<>(); - response.put("message", "Card 생성 성공"); - response.put("card", result); - - return ResponseEntity.status(HttpStatus.CREATED).body(response); - } catch (Exception e) { - - Map errorResponse = new HashMap<>(); - errorResponse.put("message", "Error 발생"); - errorResponse.put("error", e.getMessage()); - - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); - } - } - - @GetMapping("/{id}") - public ResponseEntity getCardById(@PathVariable Long id) { - try { - Card card = cardService.getCardById(id); - if (card == null) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("해당 Card가 존재하지 않음"); - } - return ResponseEntity.ok(card); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error 발생"); - } - } - - @GetMapping() - public ResponseEntity getAllCards() { - try { - List cards = cardService.getAllCards(); - if (cards.isEmpty()) { - return ResponseEntity.status(HttpStatus.NO_CONTENT).body("카드가 존재하지 않음"); - } - return ResponseEntity.ok(cards); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error 발생"); - } - } - - @DeleteMapping("/{id}") - public ResponseEntity> deleteCard(@PathVariable Long id) { - cardService.deleteCard(id); - - Map response = new HashMap<>(); - response.put("message", "Card 삭제 완료"); - - return ResponseEntity.ok(response); - } - - @PostMapping("/update/{id}") - public ResponseEntity updateCard(@PathVariable Long id, @RequestBody Card updatedCard) { - Card newCard = cardService.updateCard(id, updatedCard); - - if (newCard == null) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("카드가 존재하지 않음"); - } else { - return ResponseEntity.ok(newCard); - } - } -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java b/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java deleted file mode 100644 index 741e648..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/CardRepository.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.likelion.trendithon.domain.card; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CardRepository extends JpaRepository {} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java b/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java deleted file mode 100644 index aee995c..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/CardResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.likelion.trendithon.domain.card; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class CardResponseDto { - - private Long cardId; - private String title; - - public CardResponseDto(Long id, String title) { - this.cardId = id; - this.title = title; - } -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/CardService.java b/src/main/java/com/likelion/trendithon/domain/card/CardService.java deleted file mode 100644 index 01ea6f6..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/CardService.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.likelion.trendithon.domain.card; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.springframework.stereotype.Service; - -import com.likelion.trendithon.domain.tag.Tag; -import com.likelion.trendithon.domain.tag.TagService; - -import lombok.AllArgsConstructor; - -@Service -@AllArgsConstructor -public class CardService { - - private CardRepository cardRepository; - private TagService tagService; - - public Card createCard(Card card) { - List tags = card.getTagItems(); - tagService.createTag(tags); - return cardRepository.save(card); - } - - public Card getCardById(Long id) { - Optional optionalCard = cardRepository.findById(id); - Card card; - if (optionalCard.isPresent()) { - card = optionalCard.get(); - card.setTagItems(tagService.getTags(card)); - return card; - } - - return null; - } - - public List getAllCards() { - List cardList = cardRepository.findAll(); - List cardDtos = new ArrayList<>(); - - for (Card card : cardList) { - cardDtos.add(new CardResponseDto(card.getCardId(), card.getTitle())); - } - - return cardDtos; - } - - public void deleteCard(Long id) { - Optional optionalCard = cardRepository.findById(id); - optionalCard.ifPresent(card -> cardRepository.delete(card)); - } - - public Card updateCard(Long id, Card updatedCard) { - Optional optionalCard = cardRepository.findById(id); - Card newCard; - if (optionalCard.isPresent()) { - newCard = optionalCard.get(); - List newTags = tagService.updateTags(newCard); - - newCard.setTagItems(newTags); - newCard.setContent(updatedCard.getContent()); - newCard.setTitle(updatedCard.getTitle()); - newCard.setImgUrl(updatedCard.getImgUrl()); - - return cardRepository.save(newCard); - } else return null; - } -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java b/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java new file mode 100644 index 0000000..b44bee6 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java @@ -0,0 +1,57 @@ +package com.likelion.trendithon.domain.card.controller; + +import com.likelion.trendithon.domain.card.dto.CardUpdateDto; +import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.card.service.CardService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/cards") +@Tag(name = "Card", description = "Card 관리 API") +public class CardController { + + private CardService cardService; + + @Operation(summary = "[ 토큰 O | 카드 등록 ]", description = "새로운 카드 등록") + @PostMapping("/create") + public ResponseEntity createCard(@RequestBody Card card) { + return cardService.createCard(card); + } + + @Operation(summary = "[ 토큰 O | 카드 조회 ]", description = "ID를 통해 특정 카드 조회") + @GetMapping("/{id}") + public ResponseEntity getCardById(@PathVariable Long id) { + return cardService.getCardById(id); + } + + @Operation(summary = "[ 토큰 O | 카드 목록 조회 ]", description = "사용자 ID를 통해 특정 카드 조회") + @GetMapping("/all/{userId}") + public ResponseEntity getAllCards(@PathVariable Long userId) { + return cardService.getAllCards(userId); + } + + @Operation(summary = "[ 토큰 O | 카드 삭제 ]", description = "ID를 통해 특정 카드 삭제") + @DeleteMapping("/{id}") + public ResponseEntity deleteCard(@PathVariable Long id) { + return cardService.deleteCard(id); + } + + @Operation(summary = "[ 토큰 O | 카드 수정 ]", description = "ID를 통해 특정 카드 수정") + @PostMapping("/update/{id}") + public ResponseEntity updateCard(@PathVariable Long id, @RequestBody CardUpdateDto updatedCard) { + return cardService.updateCard(id, updatedCard); + } +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java new file mode 100644 index 0000000..9ee3e29 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java @@ -0,0 +1,22 @@ +package com.likelion.trendithon.domain.card.dto; + +import com.likelion.trendithon.domain.card.entity.Card; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class CardListResponse { + + @Schema(description = "ī ", example = "true") + private boolean success; + + @Schema(description = " ޼", example = " ī尡 Ǿϴ.") + private String message; + + @Schema(description = " ī Ʈ") + private List cardList; + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java new file mode 100644 index 0000000..9f16d60 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java @@ -0,0 +1,23 @@ +package com.likelion.trendithon.domain.card.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@Builder +@NoArgsConstructor +public class CardListSummaryDto { + + @Schema(description = "카드 Id", example = "1234") + private Long cardId; + + @Schema(description = "카드 제목", example = "멋쟁이사자 되기") + private String title; + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java new file mode 100644 index 0000000..acbe011 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java @@ -0,0 +1,23 @@ +package com.likelion.trendithon.domain.card.dto; + +import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.tag.entity.Tag; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class CardResponse { + + @Schema(description = "ī ", example = "true") + private boolean success; + + @Schema(description = " ޼", example = "ī尡 Ͽϴ.") + private String message; + + @Schema(description = "ī") + private Card card; + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java new file mode 100644 index 0000000..0a903ed --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java @@ -0,0 +1,31 @@ +package com.likelion.trendithon.domain.card.dto; + +import com.likelion.trendithon.domain.tag.entity.Tag; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +public class CardUpdateDto { + + @Schema(description = "ī ", example = "̻ DZ") + private String title; + + @Schema(description = "ī ", example = " ڰ Ǵ.") + private String content; + + @Schema(description = "̸ Url") + private String imgUrl; + + @Schema(description = "± ", example = "[{\"title\": \"\", \"content\": \" ϱ\"}]") + private List TagItems; + +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/Card.java b/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java similarity index 57% rename from src/main/java/com/likelion/trendithon/domain/card/Card.java rename to src/main/java/com/likelion/trendithon/domain/card/entity/Card.java index 08fadd6..81fefcf 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/Card.java +++ b/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java @@ -1,5 +1,6 @@ -package com.likelion.trendithon.domain.card; +package com.likelion.trendithon.domain.card.entity; +import jakarta.persistence.Column; import java.util.*; import jakarta.persistence.CascadeType; @@ -9,26 +10,38 @@ import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import com.likelion.trendithon.domain.tag.Tag; +import com.likelion.trendithon.domain.tag.entity.Tag; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Card { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cardId; + @Column(name = "title", nullable = false) private String title; + @Column(name = "content", nullable = false) private String content; + @Column(name = "imgUrl") private String imgUrl; + @Column(name = "user_id", nullable = false) + private Long userId; + @OneToMany(mappedBy = "card", cascade = CascadeType.ALL, orphanRemoval = true) private List TagItems = new ArrayList<>(); } diff --git a/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java b/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java new file mode 100644 index 0000000..d6aa456 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java @@ -0,0 +1,9 @@ +package com.likelion.trendithon.domain.card.repository; + +import com.likelion.trendithon.domain.card.entity.Card; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CardRepository extends JpaRepository { + List findByUserId(Long id); +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java b/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java new file mode 100644 index 0000000..203769c --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java @@ -0,0 +1,136 @@ +package com.likelion.trendithon.domain.card.service; + +import com.likelion.trendithon.domain.card.dto.CardListResponse; +import com.likelion.trendithon.domain.card.dto.CardResponse; +import com.likelion.trendithon.domain.card.dto.CardUpdateDto; +import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.card.repository.CardRepository; +import com.likelion.trendithon.domain.card.dto.CardListSummaryDto; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.likelion.trendithon.domain.tag.entity.Tag; +import com.likelion.trendithon.domain.tag.Service.TagService; + +import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@Service +@AllArgsConstructor +public class CardService { + + private CardRepository cardRepository; + private TagService tagService; + + // 카드 생성 - tag도 저장함 + @Transactional + public ResponseEntity createCard(Card card) { + try { + List tags = card.getTagItems(); + tagService.createTag(tags); + cardRepository.save(card); + return ResponseEntity.ok(CardResponse.builder().success(true).message("카드가 생성 성공하였습니다.").card(card).build()); + } catch (Exception e){ + return ResponseEntity.ok(CardResponse.builder().success(false).message("카드 생성 실패하였습니다.").build()); + } + + } + + // 카드 한장 조회 + @Transactional + public ResponseEntity getCardById(Long id) { + + try { + Optional optionalCard = cardRepository.findById(id); + Card card; + + if (optionalCard.isPresent()) { + card = optionalCard.get(); + card.setTagItems(tagService.getTags(card)); + + return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 조회 성공하였습니다.").card(card).build()); + } else return ResponseEntity.ok(CardResponse.builder().success(false).message("카드가 존재하지 않습니다.").build()); + + } catch (Exception e){ + return ResponseEntity.ok(CardResponse.builder().success(false).message("카드 조회 중 오류가 발생하였습니다.").build()); + } + + } + + // 사용자 아이디로 모든 카드 목록 조회 + @Transactional + public ResponseEntity getAllCards(Long userId) { + try{ + + List cardList = cardRepository.findByUserId(userId); + List cardDtos = new ArrayList<>(); + + for (Card card : cardList) { + + // 제목이랑 카드 아이디만 추출 + cardDtos.add(CardListSummaryDto.builder().cardId(card.getCardId()).title(card.getTitle()).build()); + } + + // 카드가 존재하는지 안하는지 검사 + if (!cardDtos.isEmpty()) return ResponseEntity.ok(CardListResponse.builder().success(true).message("전체 카드가 조회 되었습니다.").cardList(cardDtos).build()); + else return ResponseEntity.ok(CardListResponse.builder().success(false).message("카드가 존재하지 않습니다.").cardList(cardDtos).build()); + + } catch (Exception e){ + return ResponseEntity.ok(CardListResponse.builder().success(false).message("사용자의 카드 목록을 조회 중 에러가 발생했습니다.").build()); + } + } + + + // 카드 삭제 + @Transactional + public ResponseEntity deleteCard(Long id) { + + try{ + Optional optionalCard = cardRepository.findById(id); + if (optionalCard.isPresent()){ + + Card card= optionalCard.get(); + cardRepository.delete(card); + return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 삭제 성공하였습니다.").card(card).build()); + + } else return ResponseEntity.ok(CardResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); + + }catch (Exception e){ + return ResponseEntity.ok(CardResponse.builder().success(false).message("카드를 삭제 중 에러가 발생했습니다.").build()); + } + + } + + // 카드 수정- 수정 시 기존 태그 리스트와 비교하여 태그 삭제 수정 추가 + @Transactional + public ResponseEntity updateCard(Long id, CardUpdateDto updatedCard) { + + try{ + + Optional optionalCard = cardRepository.findById(id); + Card newCard; + + if (optionalCard.isPresent()) { + newCard = optionalCard.get(); + List newTags = tagService.updateTags(newCard); + + newCard.setTagItems(newTags); + newCard.setContent(updatedCard.getContent()); + newCard.setTitle(updatedCard.getTitle()); + newCard.setImgUrl(updatedCard.getImgUrl()); + + return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 수정 성공하였습니다.").card(newCard).build()); + } else return ResponseEntity.ok(CardResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); + + } catch (Exception e){ + return ResponseEntity.ok(CardResponse.builder().success(false).message("카드를 수정 중 에러가 발생했습니다.").build()); + + } + + + } +} diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagService.java b/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java similarity index 78% rename from src/main/java/com/likelion/trendithon/domain/tag/TagService.java rename to src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java index 119d911..2623f58 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/TagService.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java @@ -1,13 +1,16 @@ -package com.likelion.trendithon.domain.tag; +package com.likelion.trendithon.domain.tag.Service; +import com.likelion.trendithon.domain.tag.entity.Tag; +import com.likelion.trendithon.domain.tag.repository.TagRepository; import java.util.List; import java.util.Objects; import org.springframework.stereotype.Service; -import com.likelion.trendithon.domain.card.Card; +import com.likelion.trendithon.domain.card.entity.Card; import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @Service @AllArgsConstructor @@ -15,14 +18,19 @@ public class TagService { private TagRepository tagRepository; + @Transactional public void createTag(List tags) { + tagRepository.saveAll(tags); } + @Transactional public List getTags(Card card) { + return tagRepository.findByCard(card); } + @Transactional public List updateTags(Card card) { List tags = tagRepository.findByCard(card); diff --git a/src/main/java/com/likelion/trendithon/domain/tag/Tag.java b/src/main/java/com/likelion/trendithon/domain/tag/entity/Tag.java similarity index 60% rename from src/main/java/com/likelion/trendithon/domain/tag/Tag.java rename to src/main/java/com/likelion/trendithon/domain/tag/entity/Tag.java index 5235077..c2d634d 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/Tag.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/entity/Tag.java @@ -1,4 +1,4 @@ -package com.likelion.trendithon.domain.tag; +package com.likelion.trendithon.domain.tag.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -8,22 +8,30 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; -import com.likelion.trendithon.domain.card.Card; +import com.likelion.trendithon.domain.card.entity.Card; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Entity @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class Tag { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long tagId; - @Column private String tagTitle; + @Column(name = "title", nullable = false) + private String tagTitle; + @Column(name = "content", nullable = false) private String tagContent; @ManyToOne diff --git a/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java b/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java similarity index 53% rename from src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java rename to src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java index e54022c..766c684 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/TagRepository.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java @@ -1,10 +1,11 @@ -package com.likelion.trendithon.domain.tag; +package com.likelion.trendithon.domain.tag.repository; +import com.likelion.trendithon.domain.tag.entity.Tag; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import com.likelion.trendithon.domain.card.Card; +import com.likelion.trendithon.domain.card.entity.Card; public interface TagRepository extends JpaRepository { From f2adf85c9e29732c07101c6517c7228e787b8309 Mon Sep 17 00:00:00 2001 From: rkddpfls02 Date: Sat, 22 Feb 2025 03:01:19 +0900 Subject: [PATCH 8/8] =?UTF-8?q?:sparkles:Feat:=20Card,=20Tag=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../card/controller/CardController.java | 28 +-- .../domain/card/dto/CardListResponse.java | 22 --- .../domain/card/dto/CardResponse.java | 23 --- .../domain/card/dto/CardUpdateDto.java | 31 --- .../domain/card/dto/request/CardRequest.java | 24 +++ .../domain/card/dto/response/CardDto.java | 29 +++ .../card/dto/response/CardListResponse.java | 21 ++ .../{ => response}/CardListSummaryDto.java | 3 +- .../card/dto/response/CardResponse.java | 16 ++ .../card/dto/response/CardSearchResponse.java | 19 ++ .../trendithon/domain/card/entity/Card.java | 6 +- .../card/repository/CardRepository.java | 6 +- .../domain/card/service/CardService.java | 179 ++++++++++++------ .../domain/tag/Service/TagService.java | 64 +++++-- .../trendithon/domain/tag/dto/TagDto.java | 16 ++ .../domain/tag/repository/TagRepository.java | 2 +- .../global/config/SecurityConfig.java | 4 +- 17 files changed, 320 insertions(+), 173 deletions(-) delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java delete mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/request/CardRequest.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/response/CardDto.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListResponse.java rename src/main/java/com/likelion/trendithon/domain/card/dto/{ => response}/CardListSummaryDto.java (88%) create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/response/CardResponse.java create mode 100644 src/main/java/com/likelion/trendithon/domain/card/dto/response/CardSearchResponse.java create mode 100644 src/main/java/com/likelion/trendithon/domain/tag/dto/TagDto.java diff --git a/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java b/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java index b44bee6..57c9410 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java +++ b/src/main/java/com/likelion/trendithon/domain/card/controller/CardController.java @@ -1,21 +1,21 @@ package com.likelion.trendithon.domain.card.controller; -import com.likelion.trendithon.domain.card.dto.CardUpdateDto; -import com.likelion.trendithon.domain.card.entity.Card; -import com.likelion.trendithon.domain.card.service.CardService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; - import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.likelion.trendithon.domain.card.dto.request.CardRequest; +import com.likelion.trendithon.domain.card.service.CardService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; -import org.springframework.web.bind.annotation.RestController; @RestController @AllArgsConstructor @@ -27,20 +27,20 @@ public class CardController { @Operation(summary = "[ 토큰 O | 카드 등록 ]", description = "새로운 카드 등록") @PostMapping("/create") - public ResponseEntity createCard(@RequestBody Card card) { - return cardService.createCard(card); + public ResponseEntity createCard(@RequestBody CardRequest card) { + return cardService.createCard(card); } @Operation(summary = "[ 토큰 O | 카드 조회 ]", description = "ID를 통해 특정 카드 조회") @GetMapping("/{id}") public ResponseEntity getCardById(@PathVariable Long id) { - return cardService.getCardById(id); + return cardService.getCardById(id); } @Operation(summary = "[ 토큰 O | 카드 목록 조회 ]", description = "사용자 ID를 통해 특정 카드 조회") @GetMapping("/all/{userId}") - public ResponseEntity getAllCards(@PathVariable Long userId) { - return cardService.getAllCards(userId); + public ResponseEntity getAllCards(@PathVariable String userId) { + return cardService.getAllCards(userId); } @Operation(summary = "[ 토큰 O | 카드 삭제 ]", description = "ID를 통해 특정 카드 삭제") @@ -50,8 +50,8 @@ public ResponseEntity deleteCard(@PathVariable Long id) { } @Operation(summary = "[ 토큰 O | 카드 수정 ]", description = "ID를 통해 특정 카드 수정") - @PostMapping("/update/{id}") - public ResponseEntity updateCard(@PathVariable Long id, @RequestBody CardUpdateDto updatedCard) { + @PutMapping("/update/{id}") + public ResponseEntity updateCard(@PathVariable Long id, @RequestBody CardRequest updatedCard) { return cardService.updateCard(id, updatedCard); } } diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java deleted file mode 100644 index 9ee3e29..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.likelion.trendithon.domain.card.dto; - -import com.likelion.trendithon.domain.card.entity.Card; -import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class CardListResponse { - - @Schema(description = "ī ", example = "true") - private boolean success; - - @Schema(description = " ޼", example = " ī尡 Ǿϴ.") - private String message; - - @Schema(description = " ī Ʈ") - private List cardList; - -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java deleted file mode 100644 index acbe011..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/dto/CardResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.likelion.trendithon.domain.card.dto; - -import com.likelion.trendithon.domain.card.entity.Card; -import com.likelion.trendithon.domain.tag.entity.Tag; -import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class CardResponse { - - @Schema(description = "ī ", example = "true") - private boolean success; - - @Schema(description = " ޼", example = "ī尡 Ͽϴ.") - private String message; - - @Schema(description = "ī") - private Card card; - -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java b/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java deleted file mode 100644 index 0a903ed..0000000 --- a/src/main/java/com/likelion/trendithon/domain/card/dto/CardUpdateDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.likelion.trendithon.domain.card.dto; - -import com.likelion.trendithon.domain.tag.entity.Tag; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -public class CardUpdateDto { - - @Schema(description = "ī ", example = "̻ DZ") - private String title; - - @Schema(description = "ī ", example = " ڰ Ǵ.") - private String content; - - @Schema(description = "̸ Url") - private String imgUrl; - - @Schema(description = "± ", example = "[{\"title\": \"\", \"content\": \" ϱ\"}]") - private List TagItems; - -} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/request/CardRequest.java b/src/main/java/com/likelion/trendithon/domain/card/dto/request/CardRequest.java new file mode 100644 index 0000000..2322867 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/request/CardRequest.java @@ -0,0 +1,24 @@ +package com.likelion.trendithon.domain.card.dto.request; + +import java.util.List; + +import com.likelion.trendithon.domain.tag.dto.TagDto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +public class CardRequest { + + @Schema(description = "카드 제목", example = "멋쟁이사자 되기") + private String title; + + @Schema(description = "카드 내용", example = "나는 오늘 멋쟁이 사자가 되다.") + private String content; + + @Schema(description = "이모지 Url") + private String imgUrl; + + @Schema(description = "태그 목록", example = "[{\"tagTitle\": \"팁\", \"tagContent\": \"열심히 하기\"}]") + private List tagItems; +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardDto.java b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardDto.java new file mode 100644 index 0000000..d73b05d --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardDto.java @@ -0,0 +1,29 @@ +package com.likelion.trendithon.domain.card.dto.response; + +import java.util.List; + +import com.likelion.trendithon.domain.tag.dto.TagDto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class CardDto { + + @Schema(description = "카드 제목", example = "멋쟁이사자 되기") + private String title; + + @Schema(description = "카드 내용", example = "나는 오늘 멋쟁이 사자가 되다.") + private String content; + + @Schema(description = "이모지 Url") + private String imgUrl; + + @Schema(description = "사용자 Id", example = "likelion") + private String userId; + + @Schema(description = "태그 목록", example = "[{\"tagTitle\": \"팁\", \"tagContent\": \"열심히 하기\"}]") + private List tagItems; +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListResponse.java new file mode 100644 index 0000000..fb12184 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListResponse.java @@ -0,0 +1,21 @@ +package com.likelion.trendithon.domain.card.dto.response; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class CardListResponse { + + @Schema(description = "카드 생성 결과", example = "true") + private boolean success; + + @Schema(description = "응답 메세지", example = "성공적으로 카드가 생성되었습니다.") + private String message; + + @Schema(description = "보유한 카드 리스트") + private List cardList; +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListSummaryDto.java similarity index 88% rename from src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java rename to src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListSummaryDto.java index 9f16d60..17b53e2 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/dto/CardListSummaryDto.java +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardListSummaryDto.java @@ -1,4 +1,4 @@ -package com.likelion.trendithon.domain.card.dto; +package com.likelion.trendithon.domain.card.dto.response; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; @@ -19,5 +19,4 @@ public class CardListSummaryDto { @Schema(description = "카드 제목", example = "멋쟁이사자 되기") private String title; - } diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardResponse.java new file mode 100644 index 0000000..883cbe8 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardResponse.java @@ -0,0 +1,16 @@ +package com.likelion.trendithon.domain.card.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class CardResponse { + + @Schema(description = "카드 생성 결과", example = "true") + private boolean success; + + @Schema(description = "응답 메세지", example = "카드가 생성 성공하였습니다.") + private String message; +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardSearchResponse.java b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardSearchResponse.java new file mode 100644 index 0000000..4afecb3 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/card/dto/response/CardSearchResponse.java @@ -0,0 +1,19 @@ +package com.likelion.trendithon.domain.card.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class CardSearchResponse { + + @Schema(description = "카드 조회 결과", example = "true") + private boolean success; + + @Schema(description = "응답 메세지", example = "카드가 조회 성공하였습니다.") + private String message; + + @Schema(description = "카드") + private CardDto card; +} diff --git a/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java b/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java index 81fefcf..7f8258d 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java +++ b/src/main/java/com/likelion/trendithon/domain/card/entity/Card.java @@ -1,9 +1,9 @@ package com.likelion.trendithon.domain.card.entity; -import jakarta.persistence.Column; import java.util.*; import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -39,8 +39,8 @@ public class Card { @Column(name = "imgUrl") private String imgUrl; - @Column(name = "user_id", nullable = false) - private Long userId; + @Column(name = "user_id") + private String userId; @OneToMany(mappedBy = "card", cascade = CascadeType.ALL, orphanRemoval = true) private List TagItems = new ArrayList<>(); diff --git a/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java b/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java index d6aa456..28ac040 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java +++ b/src/main/java/com/likelion/trendithon/domain/card/repository/CardRepository.java @@ -1,9 +1,11 @@ package com.likelion.trendithon.domain.card.repository; -import com.likelion.trendithon.domain.card.entity.Card; import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import com.likelion.trendithon.domain.card.entity.Card; + public interface CardRepository extends JpaRepository { - List findByUserId(Long id); + List findByUserId(String id); } diff --git a/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java b/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java index 203769c..c099e02 100644 --- a/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java +++ b/src/main/java/com/likelion/trendithon/domain/card/service/CardService.java @@ -1,26 +1,30 @@ package com.likelion.trendithon.domain.card.service; -import com.likelion.trendithon.domain.card.dto.CardListResponse; -import com.likelion.trendithon.domain.card.dto.CardResponse; -import com.likelion.trendithon.domain.card.dto.CardUpdateDto; -import com.likelion.trendithon.domain.card.entity.Card; -import com.likelion.trendithon.domain.card.repository.CardRepository; -import com.likelion.trendithon.domain.card.dto.CardListSummaryDto; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import com.likelion.trendithon.domain.tag.entity.Tag; +import com.likelion.trendithon.domain.card.dto.request.CardRequest; +import com.likelion.trendithon.domain.card.dto.response.CardDto; +import com.likelion.trendithon.domain.card.dto.response.CardListResponse; +import com.likelion.trendithon.domain.card.dto.response.CardListSummaryDto; +import com.likelion.trendithon.domain.card.dto.response.CardResponse; +import com.likelion.trendithon.domain.card.dto.response.CardSearchResponse; +import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.card.repository.CardRepository; import com.likelion.trendithon.domain.tag.Service.TagService; +import com.likelion.trendithon.domain.tag.dto.TagDto; import lombok.AllArgsConstructor; -import org.springframework.transaction.annotation.Transactional; +import lombok.extern.slf4j.Slf4j; @Service @AllArgsConstructor +@Slf4j public class CardService { private CardRepository cardRepository; @@ -28,21 +32,29 @@ public class CardService { // 카드 생성 - tag도 저장함 @Transactional - public ResponseEntity createCard(Card card) { + public ResponseEntity createCard(CardRequest card) { try { - List tags = card.getTagItems(); - tagService.createTag(tags); - cardRepository.save(card); - return ResponseEntity.ok(CardResponse.builder().success(true).message("카드가 생성 성공하였습니다.").card(card).build()); - } catch (Exception e){ - return ResponseEntity.ok(CardResponse.builder().success(false).message("카드 생성 실패하였습니다.").build()); + List tags = card.getTagItems(); + Card newCard = + Card.builder() + .title(card.getTitle()) + .content(card.getContent()) + .imgUrl(card.getImgUrl()) + .build(); + cardRepository.save(newCard); + tagService.saveTag(tags, newCard); + + return ResponseEntity.ok( + CardResponse.builder().success(true).message("카드가 생성 성공하였습니다.").build()); + } catch (Exception e) { + return ResponseEntity.ok( + CardResponse.builder().success(false).message("카드 생성 실패하였습니다.").build()); } - } // 카드 한장 조회 @Transactional - public ResponseEntity getCardById(Long id) { + public ResponseEntity getCardById(Long id) { try { Optional optionalCard = cardRepository.findById(id); @@ -50,21 +62,43 @@ public ResponseEntity getCardById(Long id) { if (optionalCard.isPresent()) { card = optionalCard.get(); - card.setTagItems(tagService.getTags(card)); - - return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 조회 성공하였습니다.").card(card).build()); - } else return ResponseEntity.ok(CardResponse.builder().success(false).message("카드가 존재하지 않습니다.").build()); - } catch (Exception e){ - return ResponseEntity.ok(CardResponse.builder().success(false).message("카드 조회 중 오류가 발생하였습니다.").build()); + List tags = + card.getTagItems().stream() + .map( + tag -> + TagDto.builder() + .tagTitle(tag.getTagTitle()) + .tagContent(tag.getTagContent()) + .build()) + .toList(); + + return ResponseEntity.ok( + CardSearchResponse.builder() + .success(true) + .message("카드 조회 성공하였습니다.") + .card( + CardDto.builder() + .title(card.getTitle()) + .content(card.getContent()) + .imgUrl(card.getImgUrl()) + .tagItems(tags) + .build()) + .build()); + } else + return ResponseEntity.ok( + CardSearchResponse.builder().success(false).message("카드가 존재하지 않습니다.").build()); + + } catch (Exception e) { + return ResponseEntity.ok( + CardSearchResponse.builder().success(false).message("카드 조회 중 오류가 발생하였습니다.").build()); } - } // 사용자 아이디로 모든 카드 목록 조회 @Transactional - public ResponseEntity getAllCards(Long userId) { - try{ + public ResponseEntity getAllCards(String userId) { + try { List cardList = cardRepository.findByUserId(userId); List cardDtos = new ArrayList<>(); @@ -72,65 +106,104 @@ public ResponseEntity getAllCards(Long userId) { for (Card card : cardList) { // 제목이랑 카드 아이디만 추출 - cardDtos.add(CardListSummaryDto.builder().cardId(card.getCardId()).title(card.getTitle()).build()); + cardDtos.add( + CardListSummaryDto.builder().cardId(card.getCardId()).title(card.getTitle()).build()); } // 카드가 존재하는지 안하는지 검사 - if (!cardDtos.isEmpty()) return ResponseEntity.ok(CardListResponse.builder().success(true).message("전체 카드가 조회 되었습니다.").cardList(cardDtos).build()); - else return ResponseEntity.ok(CardListResponse.builder().success(false).message("카드가 존재하지 않습니다.").cardList(cardDtos).build()); - - } catch (Exception e){ - return ResponseEntity.ok(CardListResponse.builder().success(false).message("사용자의 카드 목록을 조회 중 에러가 발생했습니다.").build()); + if (!cardDtos.isEmpty()) + return ResponseEntity.ok( + CardListResponse.builder() + .success(true) + .message("전체 카드가 조회 되었습니다.") + .cardList(cardDtos) + .build()); + else + return ResponseEntity.ok( + CardListResponse.builder() + .success(false) + .message("카드가 존재하지 않습니다.") + .cardList(cardDtos) + .build()); + + } catch (Exception e) { + return ResponseEntity.ok( + CardListResponse.builder() + .success(false) + .message("사용자의 카드 목록을 조회 중 에러가 발생했습니다.") + .build()); } } - // 카드 삭제 @Transactional public ResponseEntity deleteCard(Long id) { - try{ + try { Optional optionalCard = cardRepository.findById(id); - if (optionalCard.isPresent()){ + if (optionalCard.isPresent()) { - Card card= optionalCard.get(); + Card card = optionalCard.get(); cardRepository.delete(card); - return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 삭제 성공하였습니다.").card(card).build()); + return ResponseEntity.ok( + CardResponse.builder().success(true).message("카드 삭제 성공하였습니다.").build()); - } else return ResponseEntity.ok(CardResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); + } else + return ResponseEntity.ok( + CardResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); - }catch (Exception e){ - return ResponseEntity.ok(CardResponse.builder().success(false).message("카드를 삭제 중 에러가 발생했습니다.").build()); + } catch (Exception e) { + return ResponseEntity.ok( + CardResponse.builder().success(false).message("카드를 삭제 중 에러가 발생했습니다.").build()); } - } // 카드 수정- 수정 시 기존 태그 리스트와 비교하여 태그 삭제 수정 추가 @Transactional - public ResponseEntity updateCard(Long id, CardUpdateDto updatedCard) { + public ResponseEntity updateCard(Long id, CardRequest updatedCard) { - try{ + try { Optional optionalCard = cardRepository.findById(id); Card newCard; if (optionalCard.isPresent()) { newCard = optionalCard.get(); - List newTags = tagService.updateTags(newCard); + tagService.updateTags(newCard, updatedCard.getTagItems()); - newCard.setTagItems(newTags); newCard.setContent(updatedCard.getContent()); newCard.setTitle(updatedCard.getTitle()); newCard.setImgUrl(updatedCard.getImgUrl()); - return ResponseEntity.ok(CardResponse.builder().success(true).message("카드 수정 성공하였습니다.").card(newCard).build()); - } else return ResponseEntity.ok(CardResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); - - } catch (Exception e){ - return ResponseEntity.ok(CardResponse.builder().success(false).message("카드를 수정 중 에러가 발생했습니다.").build()); - + List tags = + newCard.getTagItems().stream() + .map( + tag -> + TagDto.builder() + .tagTitle(tag.getTagTitle()) + .tagContent(tag.getTagContent()) + .build()) + .toList(); + + return ResponseEntity.ok( + CardSearchResponse.builder() + .success(true) + .message("카드 수정 성공하였습니다.") + .card( + CardDto.builder() + .title(newCard.getTitle()) + .content(newCard.getContent()) + .imgUrl(newCard.getImgUrl()) + .tagItems(tags) + .build()) + .build()); + } else + return ResponseEntity.ok( + CardSearchResponse.builder().success(false).message("해당 카드가 존재하지 않습니다.").build()); + + } catch (Exception e) { + return ResponseEntity.ok( + CardSearchResponse.builder().success(false).message("카드 수정 중 에러가 발생했습니다.").build()); } - - } } diff --git a/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java b/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java index 2623f58..1fc4ea3 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/Service/TagService.java @@ -1,27 +1,38 @@ package com.likelion.trendithon.domain.tag.Service; -import com.likelion.trendithon.domain.tag.entity.Tag; -import com.likelion.trendithon.domain.tag.repository.TagRepository; import java.util.List; import java.util.Objects; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.tag.dto.TagDto; +import com.likelion.trendithon.domain.tag.entity.Tag; +import com.likelion.trendithon.domain.tag.repository.TagRepository; import lombok.AllArgsConstructor; -import org.springframework.transaction.annotation.Transactional; +import lombok.extern.slf4j.Slf4j; @Service @AllArgsConstructor +@Slf4j public class TagService { private TagRepository tagRepository; - @Transactional - public void createTag(List tags) { - - tagRepository.saveAll(tags); + public void saveTag(List tags, Card newCard) { + List newTags = + tags.stream() + .map( + tagDto -> + Tag.builder() + .tagTitle(tagDto.getTagTitle()) + .tagContent(tagDto.getTagContent()) + .card(newCard) + .build()) + .toList(); + tagRepository.saveAll(newTags); } @Transactional @@ -31,35 +42,48 @@ public List getTags(Card card) { } @Transactional - public List updateTags(Card card) { + public void updateTags(Card card, List newTags) { List tags = tagRepository.findByCard(card); - List newTags = card.getTagItems(); // tags엔 존재하는데 newTags에 존재하지 않으면 삭제 같으면 업뎃 for (Tag tag : tags) { - for (Tag newTag : newTags) { - if (Objects.equals(tag.getTagId(), newTag.getTagId())) { + boolean found = false; + for (TagDto newTag : newTags) { + if (Objects.equals(tag.getTagTitle(), newTag.getTagTitle())) { tag.setTagTitle(newTag.getTagTitle()); tag.setTagContent(newTag.getTagContent()); - break; + found = true; } } - tags.remove(tag); - tagRepository.delete(tag); + if (!found) { + tagRepository.delete(tag); + } } // newTags엔 존재하는데 tags엔 존재하지 않으면 추가 - for (Tag newTag : newTags) { + for (TagDto newTag : newTags) { + // 기존 [1,2,3,4] 업데이트 [2,3,6] + boolean found = false; + for (Tag tag : tags) { - if (Objects.equals(tag.getTagId(), newTag.getTagId())) break; + if (Objects.equals(tag.getTagTitle(), newTag.getTagTitle())) { + found = true; + break; + } } - tags.add(newTag); - tagRepository.save(newTag); - } + if (!found) { - return tags; + Tag tmp = + Tag.builder() + .tagTitle(newTag.getTagTitle()) + .tagContent(newTag.getTagContent()) + .card(card) + .build(); + tagRepository.save(tmp); + } + } } } diff --git a/src/main/java/com/likelion/trendithon/domain/tag/dto/TagDto.java b/src/main/java/com/likelion/trendithon/domain/tag/dto/TagDto.java new file mode 100644 index 0000000..ce69705 --- /dev/null +++ b/src/main/java/com/likelion/trendithon/domain/tag/dto/TagDto.java @@ -0,0 +1,16 @@ +package com.likelion.trendithon.domain.tag.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class TagDto { + + @Schema(description = "태그 제목", example = "팁") + private String tagTitle; + + @Schema(description = "태그 내용", example = "열심히 공부하기") + private String tagContent; +} diff --git a/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java b/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java index 766c684..3a06b72 100644 --- a/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java +++ b/src/main/java/com/likelion/trendithon/domain/tag/repository/TagRepository.java @@ -1,11 +1,11 @@ package com.likelion.trendithon.domain.tag.repository; -import com.likelion.trendithon.domain.tag.entity.Tag; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import com.likelion.trendithon.domain.card.entity.Card; +import com.likelion.trendithon.domain.tag.entity.Tag; public interface TagRepository extends JpaRepository { diff --git a/src/main/java/com/likelion/trendithon/global/config/SecurityConfig.java b/src/main/java/com/likelion/trendithon/global/config/SecurityConfig.java index 6f5b8de..3bcd1f8 100644 --- a/src/main/java/com/likelion/trendithon/global/config/SecurityConfig.java +++ b/src/main/java/com/likelion/trendithon/global/config/SecurityConfig.java @@ -42,8 +42,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/", "/api/**", // 테스트용 모든 API 열어놓음. 나중에 삭제 "/swagger-ui/**", // Swagger UI - "/v3/api-docs/**" // API 문서 - ) + "/v3/api-docs/**", // API 문서 + "/api/cards/**") .permitAll() // 관리자 권한이 필요한 경로 설정 // .requestMatchers(HttpMethod.POST, "/api/**")