Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

레시피 리스트 fetch 데이터 관련 로직 수정 #37

Merged
merged 4 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,35 @@ 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"
}
}

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()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]>
}

Expand All @@ -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<RecipePageDTO>.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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Result<[Recipe], Error>>(value: .success([]))

init(fetchFeedListUseCase: FetchFeedListUseCase, searchFeedListUseCase: SearchFeedListUseCase) {
self.fetchFeedListUseCase = fetchFeedListUseCase
self.searchFeedListUseCase = searchFeedListUseCase
}

func viewDidLoad() {
fetchRecipes()
}
Expand All @@ -54,7 +55,7 @@ class RecipeListInteractorImpl: RecipeListInteractor {
fetchNextRecipes()
}
}

func didSelectItem(ID: Int) {
delegate?.showRecipeDetail(ID: ID)
}
Expand All @@ -67,7 +68,7 @@ class RecipeListInteractorImpl: RecipeListInteractor {
recipesSubject.onNext(.success([]))
fetchRecipes()
}

func searchRecipes(with title: String) {
guard !isFetching else { return }
isFetching = true
Expand All @@ -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() {
Expand Down Expand Up @@ -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))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import RxSwift

protocol FetchFeedListUseCase {
func execute(pageNumber: Int) -> Single<Result<[Recipe], Error>>
func execute(currentPage: Int, targetPage: Int, boundaryID: Int) -> Single<Result<[Recipe], Error>>
}

class FetchFeedListUseCaseImpl: FetchFeedListUseCase {
Expand All @@ -18,13 +18,17 @@ class FetchFeedListUseCaseImpl: FetchFeedListUseCase {
self.repository = repository
}

func execute(pageNumber: Int) -> Single<Result<[Recipe], Error>> {
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<Result<[Recipe], Error>> {
return repository.fetchRecipes(
currentPage: currentPage,
targetPage: targetPage,
boundaryID: boundaryID
)
.map { recipes in
return .success(recipes)
}
.catch { error in
return .just(.failure(error))
}
}
}
Loading