From 480d5fa86e67deb83990d07007190bb2fe4aa334 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 8 Jan 2025 20:31:29 +0900 Subject: [PATCH 1/4] =?UTF-8?q?Fix:=20=EB=A0=88=EC=8B=9C=ED=94=BC=EB=93=A4?= =?UTF-8?q?=EC=9D=84=20=EB=B0=9B=EC=95=84=EC=98=A4=EB=8A=94=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EB=84=A4=EC=9D=B4=EB=B0=8D=EA=B3=BC=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/DTO/RecipeDTO.swift | 24 +++++++------------ .../Data/Network/DTO/RecipeDetailDTO.swift | 11 ++++----- .../Data/Network/DTO/RecipePageDTO.swift | 2 ++ .../Network/DTO/RecipeUploadResponseDTO.swift | 4 ++-- 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDTO.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDTO.swift index 6f1d198..b893101 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDTO.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDTO.swift @@ -9,25 +9,19 @@ import Foundation struct RecipeDTO: Decodable { - let id: Int - let type: String + let ID: Int let name: String - let description: String let likesCount: Int - let createdAt: String let writer: UserDTO - let imageUrls: [RecipeImageDTO] + let recipeImageUrl: String let isLikedByCurrentUser: Bool enum CodingKeys: String, CodingKey { - case id = "recipeId" - case type = "recipeType" + case ID = "recipeId" case name = "recipeName" - case description = "recipeDescription" case likesCount = "recipeLikesCnt" - case createdAt = "createdAt" case writer = "writer" - case imageUrls = "recipeImgUrls" + case recipeImageUrl = "recipeImageUrl" case isLikedByCurrentUser = "isLiked" } } @@ -35,15 +29,15 @@ struct RecipeDTO: Decodable { extension RecipeDTO { func toDomain() -> Recipe { return Recipe( - id: id, - type: RecipeType(rawValue: type) ?? .coffee, + id: ID, + type: .coffee, // MARK: 임시 값 커피로 설정 name: name, - description: description, + description: "", writer: writer.toDomain(), - imageUrls: imageUrls.map { $0.recipeImageUrl }, + imageUrls: [recipeImageUrl], isLikedByCurrentUser: isLikedByCurrentUser, likeCount: likesCount, - createdAt: DateFormatter.iso8601.date(from: createdAt) ?? Date() + createdAt: Date() ) } } diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift index 0c11bfa..b11c7cb 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift @@ -8,20 +8,17 @@ import Foundation struct RecipeDetailDTO: Decodable { - let id: Int - let type: String let name: String let description: String let likesCount: Int let createdAt: String let writer: UserDTO - let imageUrls: [RecipeImageDTO] + let imageUrls: [String] // 배열로 수신 let isLikedByCurrentUser: Bool enum CodingKeys: String, CodingKey { case id = "recipeId" - case type = "recipeType" case name = "recipeName" case description = "recipeDescription" case likesCount = "recipeLikesCnt" @@ -35,12 +32,12 @@ struct RecipeDetailDTO: Decodable { extension RecipeDetailDTO { func toDomain() -> Recipe { return Recipe( - id: id, - type: RecipeType(rawValue: type) ?? .coffee, + id: id, + type: .coffee, name: name, description: description, writer: writer.toDomain(), - imageUrls: imageUrls.map { $0.recipeImageUrl }, + imageUrls: imageUrls, isLikedByCurrentUser: isLikedByCurrentUser, likeCount: likesCount, createdAt: DateFormatter.iso8601.date(from: createdAt) ?? Date() diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipePageDTO.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipePageDTO.swift index 7a72985..c2613cd 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipePageDTO.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipePageDTO.swift @@ -10,11 +10,13 @@ import Foundation struct RecipePageDTO: Decodable { let totalPageNumber: Int let pageNumber: Int + let lastBoundaryId: Int let recipes: [RecipeDTO] private enum CodingKeys: String, CodingKey { case totalPageNumber = "totalPageNumber" case pageNumber = "pageNumber" + case lastBoundaryId = "lastBoundaryId" case recipes = "recipes" } } diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeUploadResponseDTO.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeUploadResponseDTO.swift index bbfc8c6..c42f932 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeUploadResponseDTO.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeUploadResponseDTO.swift @@ -16,7 +16,7 @@ struct RecipeUploadResponseDTO: Decodable { let likesCount: Int let createdAt: String let writer: UserDTO - let imageUrls: [RecipeImageDTO] + let imageUrls: [String] let isLikedByCurrentUser: Bool enum CodingKeys: String, CodingKey { @@ -41,7 +41,7 @@ extension RecipeUploadResponseDTO { name: name, description: description, writer: writer.toDomain(), - imageUrls: imageUrls.map { $0.recipeImageUrl }, + imageUrls: imageUrls, isLikedByCurrentUser: isLikedByCurrentUser, likeCount: likesCount, createdAt: DateFormatter.iso8601.date(from: createdAt) ?? Date() From 9c0077a3effa7e9948f5ff3ad06c235864d1e8c2 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 8 Jan 2025 20:34:04 +0900 Subject: [PATCH 2/4] =?UTF-8?q?Fix:=20=EB=A0=88=EC=8B=9C=ED=94=BC=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=93=A4=20=EB=B6=88=EB=9F=AC?= =?UTF-8?q?=EC=98=AC=EB=95=8C=20=ED=95=84=EC=9A=94=ED=95=9C=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interactor/RecipeListInteractor.swift | 54 +++++++++++-------- .../UseCases/FetchFeedListUseCase.swift | 22 ++++---- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeListInteractor.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeListInteractor.swift index af22351..6368fdd 100755 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeListInteractor.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeListInteractor.swift @@ -28,20 +28,21 @@ class RecipeListInteractorImpl: RecipeListInteractor { private let fetchFeedListUseCase: FetchFeedListUseCase private let searchFeedListUseCase: SearchFeedListUseCase weak var delegate: RecipeListInteractorDelegate? - + private var currentPage: Int = 1 + private var boundaryID: Int = 0 private var isFetching = false private var isSearching = false private var currentSearchQuery: String? private var allRecipes: [Recipe] = [] - + private let recipesSubject = BehaviorSubject>(value: .success([])) - + init(fetchFeedListUseCase: FetchFeedListUseCase, searchFeedListUseCase: SearchFeedListUseCase) { self.fetchFeedListUseCase = fetchFeedListUseCase self.searchFeedListUseCase = searchFeedListUseCase } - + func viewDidLoad() { fetchRecipes() } @@ -54,7 +55,7 @@ class RecipeListInteractorImpl: RecipeListInteractor { fetchNextRecipes() } } - + func didSelectItem(ID: Int) { delegate?.showRecipeDetail(ID: ID) } @@ -67,7 +68,7 @@ class RecipeListInteractorImpl: RecipeListInteractor { recipesSubject.onNext(.success([])) fetchRecipes() } - + func searchRecipes(with title: String) { guard !isFetching else { return } isFetching = true @@ -82,29 +83,37 @@ class RecipeListInteractorImpl: RecipeListInteractor { }) .disposed(by: disposeBag) } - + private func fetchRecipes() { guard !isFetching else { return } isFetching = true - fetchFeedListUseCase.execute(pageNumber: currentPage) - .subscribe(onSuccess: { [weak self] result in - self?.handleResult(result) - }, onFailure: { [weak self] error in - self?.handleResult(.failure(error)) - }) - .disposed(by: disposeBag) + fetchFeedListUseCase.execute( + currentPage: currentPage, + targetPage: currentPage == 1 ? 1 : currentPage+1, + boundaryID: boundaryID + ) + .subscribe(onSuccess: { [weak self] result in + self?.handleResult(result) + }, onFailure: { [weak self] error in + self?.handleResult(.failure(error)) + }) + .disposed(by: disposeBag) } private func fetchNextRecipes() { guard !isFetching else { return } isFetching = true - fetchFeedListUseCase.execute(pageNumber: currentPage) - .subscribe(onSuccess: { [weak self] result in - self?.handleResult(result) - }, onFailure: { [weak self] error in - self?.handleResult(.failure(error)) - }) - .disposed(by: disposeBag) + fetchFeedListUseCase.execute( + currentPage: currentPage, + targetPage: currentPage == 1 ? 1 : currentPage+1, + boundaryID: boundaryID + ) + .subscribe(onSuccess: { [weak self] result in + self?.handleResult(result) + }, onFailure: { [weak self] error in + self?.handleResult(.failure(error)) + }) + .disposed(by: disposeBag) } private func fetchNextSearchRecipes() { @@ -134,6 +143,9 @@ class RecipeListInteractorImpl: RecipeListInteractor { } delegate?.fetchedRecipes(result: .success(allRecipes)) currentPage += 1 + if let maxRecipeID = recipes.map({ $0.id }).max() { + boundaryID = maxRecipeID + } case .failure(let error): delegate?.fetchedRecipes(result: .failure(error)) } diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift index 35a96e1..cb6f99d 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift @@ -8,7 +8,7 @@ import RxSwift protocol FetchFeedListUseCase { - func execute(pageNumber: Int) -> Single> + func execute(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single> } class FetchFeedListUseCaseImpl: FetchFeedListUseCase { @@ -18,13 +18,17 @@ class FetchFeedListUseCaseImpl: FetchFeedListUseCase { self.repository = repository } - func execute(pageNumber: Int) -> Single> { - return repository.fetchRecipes(pageNumber: pageNumber) - .map { recipes in - return .success(recipes) - } - .catch { error in - return .just(.failure(error)) - } + func execute(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single> { + return repository.fetchRecipes( + currentPage: currentPage, + targetPage: targetPage, + boundaryID: boundaryID + ) + .map { recipes in + return .success(recipes) + } + .catch { error in + return .just(.failure(error)) + } } } From 31e622f13c080f275cbf2b6040b0b01ea62a293d Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 8 Jan 2025 21:45:52 +0900 Subject: [PATCH 3/4] =?UTF-8?q?Fix:=20=EB=A0=88=EC=8B=9C=ED=94=BC=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/RecipeFetchService.swift | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift index b5e7147..79dc6a2 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift @@ -9,7 +9,7 @@ import Foundation import RxSwift protocol RecipeFetchService { - func fetchRecipes(pageNumber: Int) -> Single<[Recipe]> + func fetchRecipes(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single<[Recipe]> func searchRecipes(title: String, pageNumber: Int) -> Single<[Recipe]> } @@ -27,23 +27,28 @@ class RecipeFetchServiceImpl: RecipeFetchService { return URLComponents?.url } - func fetchRecipes(pageNumber: Int) -> Single<[Recipe]> { - guard let URL = makeURL( - endpoint: "recipes", - queryItems: [URLQueryItem( - name: "pageNumber", - value: String(pageNumber)) - ]) else { + func fetchRecipes( + currentPage: Int, + targetPage: Int, + boundaryID: Int + ) -> Single<[Recipe]> { + let queryItems = [ + URLQueryItem(name: "currentPage", value: String(currentPage)), + URLQueryItem(name: "targetPage", value: String(targetPage)), + URLQueryItem(name: "boundaryId", value: String(boundaryID)) + ] + + guard let URL = makeURL(endpoint: "recipes", queryItems: queryItems) else { return Single.error(NSError( domain: "URLComponentsError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) } + return networkService.getRequest(url: URL, responseType: NetworkResponseDTO.self) - .map { $0.data.recipes.map{ $0.toDomain() } } + .map { $0.data.recipes.map { $0.toDomain() } } } - func searchRecipes(title: String, pageNumber: Int) -> Single<[Recipe]> { guard let URL = makeURL(endpoint: "recipes", queryItems: [ URLQueryItem( From f37c73fa06ac54e183f17e8d505cb3c46981ca88 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 8 Jan 2025 22:02:19 +0900 Subject: [PATCH 4/4] =?UTF-8?q?Fix:=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=98=A4=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20Rep?= =?UTF-8?q?ository=EC=9D=98=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Repositories/FeedListRepository.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift index 21be892..cfe82ae 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift @@ -8,7 +8,7 @@ import RxSwift protocol FeedListRepository { - func fetchRecipes(pageNumber: Int) -> Single<[Recipe]> + func fetchRecipes(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single<[Recipe]> } class FeedListRepositoryImpl: FeedListRepository { @@ -18,7 +18,7 @@ class FeedListRepositoryImpl: FeedListRepository { self.networkService = networkService } - func fetchRecipes(pageNumber: Int) -> Single<[Recipe]> { - return networkService.fetchRecipes(pageNumber: pageNumber) + func fetchRecipes(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single<[Recipe]> { + return networkService.fetchRecipes(currentPage: currentPage, targetPage: targetPage, boundaryID: boundaryID) } }