Skip to content

Commit

Permalink
Merge pull request #33 from f-lab-edu/feature/comment
Browse files Browse the repository at this point in the history
댓글들을 로드하는 기능을 생성하였습니다.
  • Loading branch information
GeonH0 authored Oct 8, 2024
2 parents fc78273 + d047ef6 commit b4ec175
Show file tree
Hide file tree
Showing 17 changed files with 779 additions and 47 deletions.
62 changes: 62 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
objects = {

/* Begin PBXBuildFile section */
1D0173AC2CB162CA00FF04BA /* commentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0173AB2CB162CA00FF04BA /* commentViewModel.swift */; };
1D0173AE2CB171DF00FF04BA /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0173AD2CB171DF00FF04BA /* Comment.swift */; };
1D0173B02CB1847C00FF04BA /* CommentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0173AF2CB1847C00FF04BA /* CommentView.swift */; };
1D0173B22CB1856300FF04BA /* CommentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0173B12CB1856300FF04BA /* CommentViewController.swift */; };
1D0173B42CB185C000FF04BA /* CommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0173B32CB185C000FF04BA /* CommentCell.swift */; };
1D0635E12CB28A8700DCC9EA /* CommentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0635E02CB28A8700DCC9EA /* CommentService.swift */; };
1D0635E42CB28B8700DCC9EA /* CommentInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0635E32CB28B8700DCC9EA /* CommentInteractor.swift */; };
1D0635E62CB2A63200DCC9EA /* FetchCommentUsecase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0635E52CB2A63200DCC9EA /* FetchCommentUsecase.swift */; };
1D0635E82CB2AA0600DCC9EA /* CommentListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0635E72CB2AA0600DCC9EA /* CommentListRepository.swift */; };
1D0635EA2CB2B0CD00DCC9EA /* CommentDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0635E92CB2B0CD00DCC9EA /* CommentDTO.swift */; };
1D0BE5822CB5652500F54A26 /* CommnetMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D0BE5812CB5652500F54A26 /* CommnetMapper.swift */; };
1D0BE5832CB575B800F54A26 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D2C16EE2BE532B800C04508 /* Assets.xcassets */; };
1D1283A22C15E94300C5A870 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A12C15E94300C5A870 /* Recipe.swift */; };
1D1283A42C15EA8100C5A870 /* RecipeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A32C15EA8100C5A870 /* RecipeType.swift */; };
1D1283AA2C15EBCF00C5A870 /* SearchFeedUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A92C15EBCF00C5A870 /* SearchFeedUseCase.swift */; };
Expand Down Expand Up @@ -156,6 +168,17 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1D0173AB2CB162CA00FF04BA /* commentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = commentViewModel.swift; sourceTree = "<group>"; };
1D0173AD2CB171DF00FF04BA /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = "<group>"; };
1D0173AF2CB1847C00FF04BA /* CommentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentView.swift; sourceTree = "<group>"; };
1D0173B12CB1856300FF04BA /* CommentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewController.swift; sourceTree = "<group>"; };
1D0173B32CB185C000FF04BA /* CommentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCell.swift; sourceTree = "<group>"; };
1D0635E02CB28A8700DCC9EA /* CommentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentService.swift; sourceTree = "<group>"; };
1D0635E32CB28B8700DCC9EA /* CommentInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentInteractor.swift; sourceTree = "<group>"; };
1D0635E52CB2A63200DCC9EA /* FetchCommentUsecase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchCommentUsecase.swift; sourceTree = "<group>"; };
1D0635E72CB2AA0600DCC9EA /* CommentListRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentListRepository.swift; sourceTree = "<group>"; };
1D0635E92CB2B0CD00DCC9EA /* CommentDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDTO.swift; sourceTree = "<group>"; };
1D0BE5812CB5652500F54A26 /* CommnetMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommnetMapper.swift; sourceTree = "<group>"; };
1D1283A12C15E94300C5A870 /* Recipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = "<group>"; };
1D1283A32C15EA8100C5A870 /* RecipeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeType.swift; sourceTree = "<group>"; };
1D1283A92C15EBCF00C5A870 /* SearchFeedUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchFeedUseCase.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -282,6 +305,25 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
1D0173AA2CB15E2A00FF04BA /* comment */ = {
isa = PBXGroup;
children = (
1D0635E22CB28ADE00DCC9EA /* View */,
1D0173AB2CB162CA00FF04BA /* commentViewModel.swift */,
1D0173AF2CB1847C00FF04BA /* CommentView.swift */,
1D0173B12CB1856300FF04BA /* CommentViewController.swift */,
1D0173B32CB185C000FF04BA /* CommentCell.swift */,
);
path = comment;
sourceTree = "<group>";
};
1D0635E22CB28ADE00DCC9EA /* View */ = {
isa = PBXGroup;
children = (
);
path = View;
sourceTree = "<group>";
};
1D12839F2C15E7A700C5A870 /* Entities */ = {
isa = PBXGroup;
children = (
Expand All @@ -293,6 +335,7 @@
1DD4F7092C80C947003E9D9D /* LoginError.swift */,
1D2398B32C8DC23500626F0C /* SignUpError.swift */,
1DDF485A2C93DFC9000A082E /* CheckEmailError.swift */,
1D0173AD2CB171DF00FF04BA /* Comment.swift */,
);
path = Entities;
sourceTree = "<group>";
Expand All @@ -307,6 +350,7 @@
1D7641442C81BE90002AC68F /* LoginUseCase.swift */,
1D2398B12C8DC07800626F0C /* SignUpUseCase.swift */,
1DFC961F2C908739006C3309 /* CheckEmailUsecase.swift */,
1D0635E52CB2A63200DCC9EA /* FetchCommentUsecase.swift */,
);
path = UseCases;
sourceTree = "<group>";
Expand Down Expand Up @@ -338,6 +382,7 @@
1D39726B2C458CE100495014 /* MultipartFormDataRequest.swift */,
1D7641482C831295002AC68F /* LoginService.swift */,
1DBD90B82C91BDAC00184F67 /* SignUpService.swift */,
1D0635E02CB28A8700DCC9EA /* CommentService.swift */,
);
path = Network;
sourceTree = "<group>";
Expand Down Expand Up @@ -451,6 +496,7 @@
1D7368852C33D7BE000EF904 /* RecipeUploadResponseDTO.swift */,
1DBD90BA2C91DE1600184F67 /* EmptyResponse.swift */,
1DDF485C2C9405CF000A082E /* CheckEmailRespones.swift */,
1D0635E92CB2B0CD00DCC9EA /* CommentDTO.swift */,
);
path = DTO;
sourceTree = "<group>";
Expand Down Expand Up @@ -487,6 +533,7 @@
isa = PBXGroup;
children = (
1D3972672C44185B00495014 /* RecipeListMapper.swift */,
1D0BE5812CB5652500F54A26 /* CommnetMapper.swift */,
);
path = Mapper;
sourceTree = "<group>";
Expand All @@ -499,6 +546,7 @@
1D73686F2C32BFBB000EF904 /* AddRecipeInteractor.swift */,
1D96FDA92C7F55E600EFC657 /* LoginInteractor.swift */,
1DF6E1422C8C561E005E8875 /* SignUpInteractor.swift */,
1D0635E32CB28B8700DCC9EA /* CommentInteractor.swift */,
);
path = Interactor;
sourceTree = "<group>";
Expand All @@ -513,13 +561,15 @@
1D7641462C831192002AC68F /* LoginRepository.swift */,
1DFC961B2C90809D006C3309 /* SignUpRepository.swift */,
1DFC961D2C908723006C3309 /* CheckEmailRepository.swift */,
1D0635E72CB2AA0600DCC9EA /* CommentListRepository.swift */,
);
path = Repositories;
sourceTree = "<group>";
};
1DE19EB22C1B422F0031804A /* Presentation */ = {
isa = PBXGroup;
children = (
1D0173AA2CB15E2A00FF04BA /* comment */,
1DF0D1A72C7DF99F00E2C94C /* Login */,
1D2C6F662C24697F004BB54E /* UploadRecipe */,
1D2C6F612C2446AF004BB54E /* Tabbar */,
Expand Down Expand Up @@ -724,6 +774,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1D0BE5832CB575B800F54A26 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -751,6 +802,7 @@
1DBB550A2C8421920009E033 /* SignUpViewController.swift in Sources */,
1D439E9E2C2C598A008530A5 /* RecipeDetailRepository.swift in Sources */,
1D2C6F6C2C27051D004BB54E /* CustomNavigationBar.swift in Sources */,
1D0173B42CB185C000FF04BA /* CommentCell.swift in Sources */,
1DD4F70A2C80C947003E9D9D /* LoginError.swift in Sources */,
1D3972682C44185B00495014 /* RecipeListMapper.swift in Sources */,
1D2C16EA2BE532B700C04508 /* ViewController.swift in Sources */,
Expand All @@ -768,6 +820,7 @@
1DE19EB12C1B42200031804A /* NetworkService.swift in Sources */,
1DC7CC322C283C0200796889 /* RecipeUploadImgaeCell.swift in Sources */,
1D7368782C32E7FE000EF904 /* RecipePostService.swift in Sources */,
1D0635EA2CB2B0CD00DCC9EA /* CommentDTO.swift in Sources */,
1D2398B42C8DC23500626F0C /* SignUpError.swift in Sources */,
1DBC63662C47D23000DA00C2 /* AddRecipeError.swift in Sources */,
1D95A0A62C37C79500F09077 /* RecipeDetailError.swift in Sources */,
Expand All @@ -784,8 +837,12 @@
1DF829B72C2A7CDC00C337FC /* UIImageViewImageLoading.swift in Sources */,
1D5AEE532C592A9900BBD5F0 /* RecipeListItemViewModel.swift in Sources */,
1D60CC3D2C3E4F1600D08FA3 /* APIConfig.swift in Sources */,
1D0173B02CB1847C00FF04BA /* CommentView.swift in Sources */,
1D0635E42CB28B8700DCC9EA /* CommentInteractor.swift in Sources */,
1D6F99492C9291B700430FD8 /* UIViewController+Alert.swift in Sources */,
1D1283A42C15EA8100C5A870 /* RecipeType.swift in Sources */,
1D0173AC2CB162CA00FF04BA /* commentViewModel.swift in Sources */,
1D0635E62CB2A63200DCC9EA /* FetchCommentUsecase.swift in Sources */,
1D7641472C831192002AC68F /* LoginRepository.swift in Sources */,
1DF829B42C2A7A7D00C337FC /* Fonts.swift in Sources */,
1DF0D1AD2C7DF9BB00E2C94C /* LoginView.swift in Sources */,
Expand All @@ -796,19 +853,23 @@
1DBB55062C8418490009E033 /* LoginRouter.swift in Sources */,
1DFC961E2C908723006C3309 /* CheckEmailRepository.swift in Sources */,
1D1283AA2C15EBCF00C5A870 /* SearchFeedUseCase.swift in Sources */,
1D0BE5822CB5652500F54A26 /* CommnetMapper.swift in Sources */,
1DE19EA82C1B420A0031804A /* SearchFeedListRepository.swift in Sources */,
1DE19EC32C1B422F0031804A /* SearchBar.swift in Sources */,
1D439EA22C2C6997008530A5 /* RecipeDetailInteractor.swift in Sources */,
1D73686E2C305757000EF904 /* RecipeDetailDTO.swift in Sources */,
1D0635E12CB28A8700DCC9EA /* CommentService.swift in Sources */,
1D4741D72C1B4FF4009381CE /* RecipeListInteractor.swift in Sources */,
1D2398B22C8DC07800626F0C /* SignUpUseCase.swift in Sources */,
1DC7CC342C294F9200796889 /* SelectImageCell.swift in Sources */,
1DE19E9D2C1B3DC10031804A /* SceneDelegate.swift in Sources */,
1D0173B22CB1856300FF04BA /* CommentViewController.swift in Sources */,
1DDF485B2C93DFC9000A082E /* CheckEmailError.swift in Sources */,
1D4741D12C1B4F8D009381CE /* RecipeImageDTO.swift in Sources */,
1DF6E1432C8C561E005E8875 /* SignUpInteractor.swift in Sources */,
1DF0D1AB2C7DF9B500E2C94C /* LoginViewController.swift in Sources */,
1D7368742C32CF09000EF904 /* AddRecipeRepository.swift in Sources */,
1D0635E82CB2AA0600DCC9EA /* CommentListRepository.swift in Sources */,
1DE19EA72C1B420A0031804A /* FeedListRepository.swift in Sources */,
1DF0D19B2C7B92D600E2C94C /* UserDTO.swift in Sources */,
1DE19EC62C1B422F0031804A /* RecipeListCell.swift in Sources */,
Expand All @@ -822,6 +883,7 @@
1DE19EC42C1B422F0031804A /* RecipeListViewController.swift in Sources */,
1DE19EBF2C1B422F0031804A /* RecipeDetailViewModel.swift in Sources */,
1D1283A22C15E94300C5A870 /* Recipe.swift in Sources */,
1D0173AE2CB171DF00FF04BA /* Comment.swift in Sources */,
1D1283CA2C16D9C600C5A870 /* RecipeFetchService.swift in Sources */,
1D6958D42C3D059E008604B3 /* RecipeListRouter.swift in Sources */,
1D4741D42C1B4F8D009381CE /* NetworkResponseDTO.swift in Sources */,
Expand Down
37 changes: 37 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Data/Network/CommentService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// CommentService.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/6/24.
//

import UIKit

import RxSwift

protocol CommentService {
func fetchComment(recipeID: Int) -> Single<[Comment]>
}

final class CommentServiceImpl: CommentService {
private let networkService: NetworkService

init(networkService: NetworkService) {
self.networkService = networkService
}

private func makeURL(ednpoint: String) -> URL {
return APIConfig().baseURL.appendingPathComponent(ednpoint)
}

func fetchComment(recipeID: Int) -> Single<[Comment]> {
let url = makeURL(ednpoint: "comments/\(recipeID)")

return networkService.getRequest(
url: url,
responseType: NetworkResponseDTO<[CommentDTO]>.self
).map { response in
response.data.map { $0.toDomain() }
}
}
}
41 changes: 41 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/CommentDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// CommentDTO.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/6/24.
//

import Foundation

struct CommentDTO: Decodable {

let commentID: Int
let comment: String
let commentLikeCount: Int
let isLiked: Bool
let createdAt: String
let writer: UserDTO

enum CodingKeys: String, CodingKey {
case commentID = "commentId"
case comment = "content"
case commentLikeCount = "commentLikesCnt"
case isLiked = "isLiked"
case createdAt = "createdAt"
case writer = "writer"
}
}

extension CommentDTO {
func toDomain() -> Comment{
return Comment (
commentID: commentID,
comment: comment,
commentLikeCount: commentLikeCount,
isLiked: isLiked,
createAt: DateFormatter.iso8601.date(from: createdAt) ?? Date(),
writer: writer.toDomain()
)

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// CommentListRepository.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/6/24.
//

import Foundation

import RxSwift

protocol CommentListRepository {
func fetchComments(recipeID: Int) -> Single<[Comment]>
}

final class CommentListRepositoryImpl: CommentListRepository {
private let commnetServie: CommentService

init(commnetServie: CommentService) {
self.commnetServie = commnetServie
}

func fetchComments(recipeID: Int) -> Single<[Comment]> {
return commnetServie.fetchComment(recipeID: recipeID)
}
}
17 changes: 17 additions & 0 deletions HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/Comment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Comment.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/5/24.
//

import Foundation

struct Comment {
let commentID: Int
let comment: String
let commentLikeCount: Int
let isLiked: Bool
let createAt: Date
let writer: User
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// CommentInteractor.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/6/24.
//

import Foundation

import RxSwift

protocol CommentInteractorDelegate: AnyObject {
func fetchedComments(result: Result<[Comment], Error>)
}

protocol CommentInteractor {
func loadComment(recipeID: Int)
}

final class CommentInteractorImpl: CommentInteractor {
private let disposeBag = DisposeBag()
private let usecase: FetchCommentUsecase
private var allComments: [Comment] = []
weak var delegate: CommentInteractorDelegate?

init(usecase: FetchCommentUsecase) {
self.usecase = usecase
}

func loadComment(recipeID: Int) {
usecase.execute(recipeID: recipeID)
.subscribe(onSuccess: { [weak self] comments in
self?.handleResult(.success(comments))
}, onError: { [weak self] error in
self?.handleResult(.failure(error))
})
.disposed(by: disposeBag)
}

private func handleResult(_ result: Result<[Comment], Error>) {
switch result {
case .success(let comments):
if comments.isEmpty {
return
}
allComments = comments
delegate?.fetchedComments(result: .success(allComments))
case .failure(let error):
delegate?.fetchedComments(result: .failure(error))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// FetchCommentUsecase.swift
// HomeCafeRecipes
//
// Created by 김건호 on 10/6/24.
//

import RxSwift

protocol FetchCommentUsecase{
func execute(recipeID: Int) -> Single<[Comment]>
}


final class FetchCommentUsecaseImpl: FetchCommentUsecase{
private let repository: CommentListRepository

init(repository: CommentListRepository) {
self.repository = repository
}

func execute(recipeID: Int) -> Single<[Comment]> {
return repository.fetchComments(recipeID: recipeID)
}
}
Loading

0 comments on commit b4ec175

Please sign in to comment.