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

✨[Feat] add mypage review list api #65

Merged
merged 2 commits into from
Sep 1, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@
import Foundation

// 마이페이지 > 유저 작성 리뷰 목록 조회 DTO
struct MypageOffsetPageResponseDTO {
var content: [ReviewByMemberResponseDTO]?
struct MypageOffsetPageResponseDTO: Decodable {
var content: ReviewByMemberResponseDTO?
var limit: Int?
var offset: Int?
}

struct ReviewByMemberResponseDTO {
struct ReviewByMemberResponseDTO: Decodable {
var memberId: Int?
var nickname: String?
var reviewCnt: Int?
var reviewList: [ReviewDetailByMemberResponseDTO]?
}

struct ReviewDetailByMemberResponseDTO {
struct ReviewDetailByMemberResponseDTO: Decodable {
var reviewId: Int?
var rating: Float?
var rating: Double?
var reviewContents: String?
var brand: String?
var productName: String?
Expand Down
48 changes: 25 additions & 23 deletions Projects/App/Sources/Data/Mapper/Review/ReviewMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,29 @@ class ReviewMapper {
nickname: response.nickname ?? "")
}

// static func toReviewOffsetResult(response: ReviewListOffsetPageResponseDTO) -> ReviewOffsetPageResult {
// return ReviewOffsetPageResult(
// content: (response.content).compactMap { dto in
// guard let reviewId = dto.reviewId,
// let rating = dto.rating,
// let reviewContents = dto.reviewContents,
// let regDate = dto.regDate,
// let nickname = dto.nickname else {
// return nil
// }
// return ReviewDetailResult(
// reviewId: reviewId,
// rating: rating,
// reviewContents: reviewContents,
// regDate: regDate,
// nickname: nickname
// )
// },
// limit: response.limit ?? 0,
// offset: response.offset ?? 0)
// }
static func toMyReviewOffsetResult(response: MypageOffsetPageResponseDTO) -> MypageOffsetPageResult {
let content = response.content.map { dto in
ReviewByMemberResult(
memberId: dto.memberId ?? 0,
nickname: dto.nickname ?? "",
reviewCnt: dto.reviewCnt ?? 0,
reviewList: (dto.reviewList ?? []).compactMap { dto in
ReviewDetailByMemberResult(
reviewId: dto.reviewId ?? 0,
rating: dto.rating ?? 0.0,
reviewContents: dto.reviewContents ?? "",
brand: dto.brand ?? "",
productName: dto.productName ?? "",
productImage: dto.productImage ?? "",
regDate: dto.regDate ?? "")
}
)
} ?? ReviewByMemberResult(memberId: 0, nickname: "", reviewCnt: 0, reviewList: [])

return MypageOffsetPageResult(
content: content,
limit: response.limit ?? 10,
offset: response.offset ?? 0
)
}
}

//MypageOffsetPageResult ReviewMyMemberResult ReviewDetailByMemberResult
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ final class FilterRepository: FilterRepositoryProtocol {
httpMethod: .get,
endPoint: APIEndPoint.url(for: .d2CategoryList),
pathParameters: d2CategoryCode,
header: AccountStorage.shared.accessToken ?? ""
header: AccountStorage.shared.accessToken
)

switch response {
Expand Down
14 changes: 10 additions & 4 deletions Projects/App/Sources/Data/Repository/Mypage/MypageRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,20 @@ final class MypageRepository: MypageRepositoryProtocol {
func logout() -> Future<Bool, NetworkError> {
return Future { promise in
Task {
let response: Result<NoneDecodeResponse, NetworkError> = await self.apiService.request(
httpMethod: .delete,
// let response: Result<NoneDecodeResponse, NetworkError> = await self.apiService.request(
// httpMethod: .post,
// endPoint: APIEndPoint.url(for: .logout),
// header: AccountStorage.shared.accessToken
let response: Result<Bool, NetworkError> = await self.apiService.noneDecodeRequest(
httpMethod: .post,
endPoint: APIEndPoint.url(for: .logout),
header: AccountStorage.shared.accessToken
)

switch response {
case .success(let success):
promise(.success(true))
debugPrint("Logout Repo success!!")
promise(.success(success))
case .failure(let failure):
debugPrint("Failure to Logout!! \(failure.localizedDescription)")
promise(.failure(NetworkError.badRequest))
Expand All @@ -60,14 +65,15 @@ final class MypageRepository: MypageRepositoryProtocol {
func revoke() -> Future<Bool, NetworkError> {
return Future { promise in
Task {
let response: Result<NoneDecodeResponse, NetworkError> = await self.apiService.request(
let response: Result<Bool, NetworkError> = await self.apiService.noneDecodeRequest(
httpMethod: .delete,
endPoint: APIEndPoint.url(for: .signIn),
header: AccountStorage.shared.accessToken
)

switch response {
case .success(let success):
debugPrint("reovoke Repo success!!!")
promise(.success(true))
case .failure(let failure):
debugPrint("Failure to Revoke!! \(failure.localizedDescription)")
Expand Down
42 changes: 42 additions & 0 deletions Projects/App/Sources/Data/Repository/Review/ReviewRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// ReviewRepository.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import SwiftUI
import Combine

final class ReviewRepository: ReviewRepositoryProtocol {

private let apiService: ApiService

init(apiService: ApiService) {
self.apiService = apiService
}

func getMyReviewList(offset: Int?, limit: Int?) -> Future<[MypageOffsetPageResult], NetworkError> {
let parameters: [String : Int?] = ["offset" : offset ?? 0, "limit" : limit ?? 10]

return Future { promise in
Task {
let response: Result<[MypageOffsetPageResponseDTO], NetworkError> = await self.apiService.request(
httpMethod: .get,
endPoint: APIEndPoint.url(for: .userReviewList),
queryParameters: parameters,
header: AccountStorage.shared.accessToken)

switch response {
case .success(let data):
let mappedResult = data.map { ReviewMapper.toMyReviewOffsetResult(response: $0) }
promise(.success(mappedResult))
case .failure(let failure):
debugPrint("ReviewRepo > Get user review list > failed \(failure.localizedDescription)")
promise(.failure(NetworkError.badRequest))
}
}
}
}
}
96 changes: 93 additions & 3 deletions Projects/App/Sources/Data/Service/ApiService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,17 @@ final class ApiService {
}
} catch {
debugPrint("🚨🚨 <<<JSON Serialization Error>>> 🚨🚨 \(error.localizedDescription)")
return .failure(NetworkError.decode)
// return .failure(NetworkError.decode)
}

do {
let result = try JSONDecoder().decode(Response<T>.self, from: data)

if T.self == Void.self {
return .success(() as! T)
if T.self == NoneDecodeResponse.self {
guard let nonData = result.data else {
return .failure(NetworkError.response)
}
return .success(nonData)
}

debugPrint("🚨🚨 <<<Network Data>>> 🚨🚨 \(result)")
Expand All @@ -213,13 +216,100 @@ final class ApiService {
debugPrint("🚨🚨 <<<Network Decode Error>>> 🚨🚨 \(error.localizedDescription)")
return .failure(NetworkError.decode)
}

// do {
// let result = try JSONDecoder().decode(Response<T>.self, from: data)
// guard let data = result.data else {
// return .failure(NetworkError.decode)
// }
// print("🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵성공🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵🩵")
// return .success(data)
// } catch {
// debugPrint("🚨🚨 <<<Network Decode Error>>> 🚨🚨 \(error.localizedDescription)")
// return .failure(NetworkError.decode)
// }
// } catch {
// debugPrint("🚨🚨 <<< Network Error >>> 🚨🚨 \(error.localizedDescription)")
// return .failure(NetworkError.apiError)
// }
} catch {
debugPrint("🚨🚨 <<< Network Error >>> 🚨🚨 \(error.localizedDescription)")
return .failure(NetworkError.apiError)
}
}
}


extension ApiService {
func noneDecodeRequest (
httpMethod: ApiMethod,
endPoint: String,
header: String? = nil
) async -> Result<Bool, NetworkError> {

guard var url = URL(string: endPoint) else {
return .failure(NetworkError.urlError)
}

debugPrint("🚨🚨 <<<URL>>> \(url) 🚨🚨")

var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = httpMethod.rawValue

if let header = header {
urlRequest.allHTTPHeaderFields = createHeaders(token: header)
debugPrint("🚨🚨 <<<HTTP HEARDERFIELDS>>> \(String(describing: urlRequest.allHTTPHeaderFields)) 🚨🚨")
}

do {
let (data, response) = try await URLSession.shared.data(for: urlRequest)
debugPrint("🚨🚨 <<<Response>>> \(response) 🚨🚨")
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else {
return .failure(NetworkError.response)
}

print("😈😈 STATUS CODE \(statusCode) 😈😈")
let range = 200..<300
guard range.contains(statusCode) else {
return .failure(NetworkError.statusError)
}

// do {
// let jsonObject = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
// debugPrint("🚨🚨 <<<JSON Data>>> 🚨🚨 \(jsonObject)")
//
// if let jsonDict = jsonObject as? [String: Any],
// let dataDict = jsonDict["data"] as? [String: Any],
// let contentArray = dataDict["content"] as? [[String: Any]] {
// for item in contentArray {
// print("Item: \(item)")
// }
// } else {
// print("Content is empty or not a dictionary array.")
// }
// } catch {
// debugPrint("🚨🚨 <<<JSON Serialization Error>>> 🚨🚨 \(error.localizedDescription)")
// }

do {
let result = try JSONDecoder().decode(Response<NoneDecodeResponse>.self, from: data)

guard let data = result.data else {
print("🩵🩵🩵Decoding success > Data 결과 NULL > 성공🩵🩵🩵")
return .success(true)
}

return .failure(NetworkError.decode)
} catch {
debugPrint("🚨🚨 <<<Network Decode Error>>> 🚨🚨 \(error.localizedDescription)")
return .failure(NetworkError.decode)
}
} catch {
debugPrint("🚨🚨 <<< Network Error >>> 🚨🚨 \(error.localizedDescription)")
return .failure(NetworkError.apiError)
}
}
}
extension ApiService {

private func createHeaders(token: String) -> [String : String] {
Expand Down
38 changes: 38 additions & 0 deletions Projects/App/Sources/Domain/Entity/Review/MyReviewListResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// MyReviewListResult.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Foundation

// MARK: - 유저 작성 리뷰 목록 조회 api

struct MypageOffsetPageResult {
var content: ReviewByMemberResult
var limit: Int
var offset: Int
}

struct ReviewByMemberResult: Identifiable {
var memberId: Int
var nickname: String
var reviewCnt: Int
var reviewList: [ReviewDetailByMemberResult]

var id = UUID().uuidString
}

struct ReviewDetailByMemberResult: Hashable, Equatable, Identifiable {
var reviewId: Int
var rating: Double
var reviewContents: String
var brand: String
var productName: String
var productImage: String
var regDate: String

var id = UUID().uuidString
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,3 @@ struct ReviewOffsetPageResult {
var offset: Int
}

// MARK: - 마이페이지 리뷰
struct MypageOffsetPageResult {
var content: [ReviewMyMemberResult]
var limit: Int
var offset: Int
}

struct ReviewMyMemberResult {
var memberId: Int
var nickname: String
var reviewCnt: Int
var reviewList: [ReviewDetailByMemberResult]
}

struct ReviewDetailByMemberResult {
var reviewId: Int
var rating: Float
var reviewContesnt: String
var brand: String
var productName: String
var proudctImage: String
var regData: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ReviewRepositoryProtocol.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine

protocol ReviewRepositoryProtocol {
func getMyReviewList(offset: Int?, limit: Int?) -> Future<[MypageOffsetPageResult], NetworkError>
}
20 changes: 20 additions & 0 deletions Projects/App/Sources/Domain/Usecase/ReviewUsecase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// ReviewUsecase.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine

struct ReviewUsecase {

let reviewProtocol: ReviewRepositoryProtocol

func getMyReviewList(offset: Int?, limit: Int?) -> Future<[MypageOffsetPageResult], NetworkError> {
return reviewProtocol.getMyReviewList(offset: offset, limit: limit)
}


}
Loading