Skip to content

Commit 1240c2d

Browse files
authored
🔀 상품 개수 API 연결 (#33)
* ✨ Implement product count api request model and endpoint * 🚧 Create mock JSON and response model - Connected URLProtocol with mock JSON and linked the network flow in `HomeService`, setting up a foundation for network testing. * 🐛 Fix bug where mock JSON file could not be read * ✨ Connect HomeProductCount API to view
1 parent 0558b45 commit 1240c2d

File tree

14 files changed

+124
-32
lines changed

14 files changed

+124
-32
lines changed

APIService/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ let package = Package(
3232
dependencies: [
3333
"HomeAPI",
3434
],
35-
resources: [.process("HomeProductResponse.json")]
35+
resources: [.process("Mocks")]
3636
),
3737
]
3838
)

APIService/Sources/HomeAPI/HomeEndPoint.swift

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,39 @@
88
import Foundation
99
import Network
1010

11-
struct HomeEndPoint: EndPoint {
12-
let method: HTTPMethod = .get
11+
// MARK: - HomeEndPoint
1312

14-
let path: String = "v2/products"
13+
public enum HomeEndPoint {
14+
case fetchProducts(ProductRequest)
15+
case fetchCount(ProductCountRequest)
16+
}
17+
18+
// MARK: EndPoint
19+
20+
extension HomeEndPoint: EndPoint {
21+
public var method: HTTPMethod {
22+
.get
23+
}
24+
25+
public var path: String {
26+
switch self {
27+
case .fetchProducts:
28+
"/v2/products"
29+
case .fetchCount:
30+
"/v2/products/count"
31+
}
32+
}
1533

16-
let parameters: HTTPParameter = .plain
34+
public var parameters: HTTPParameter {
35+
switch self {
36+
case let .fetchProducts(requestModel):
37+
.query(requestModel)
38+
case let .fetchCount(requestModel):
39+
.query(requestModel)
40+
}
41+
}
1742

18-
let headers: [String: String] = ["Content-Type": "application/json"]
43+
public var headers: [String: String] {
44+
["Content-Type": "application/json"]
45+
}
1946
}

APIService/Sources/HomeAPI/HomeService.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import Network
1212
// MARK: - HomeServiceRepresentable
1313

1414
public protocol HomeServiceRepresentable {
15-
func fetchProductList() async throws -> [Product]
15+
func fetchProductList(request: ProductRequest) async throws -> [Product]
16+
func fetchProductCount(request: ProductCountRequest) async throws -> Int
1617
}
1718

1819
// MARK: - HomeService
@@ -28,10 +29,15 @@ public struct HomeService {
2829
// MARK: HomeServiceRepresentable
2930

3031
extension HomeService: HomeServiceRepresentable {
31-
public func fetchProductList() async throws -> [Product] {
32-
let products: [ProductResponse] = try await network.request(with: HomeEndPoint())
32+
public func fetchProductList(request: ProductRequest) async throws -> [Product] {
33+
let products: [ProductResponse] = try await network.request(with: HomeEndPoint.fetchProducts(request))
3334
return products.map(Product.init)
3435
}
36+
37+
public func fetchProductCount(request: ProductCountRequest) async throws -> Int {
38+
let countResponse: ProductCountResponse = try await network.request(with: HomeEndPoint.fetchCount(request))
39+
return countResponse.count
40+
}
3541
}
3642

3743
private extension Product {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// ProductCountRequest.swift
3+
//
4+
//
5+
// Created by 홍승현 on 2/2/24.
6+
//
7+
8+
import Entity
9+
import Foundation
10+
11+
public struct ProductCountRequest: Encodable {
12+
public let convenienceStore: ConvenienceStore
13+
14+
public init(convenienceStore: ConvenienceStore) {
15+
self.convenienceStore = convenienceStore
16+
}
17+
}

APIService/Sources/HomeAPI/Requests/ProductRequest.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,12 @@ public struct ProductRequest: Encodable {
1414
public let order: Order
1515
public let pageSize: Int
1616
public let offset: Int
17+
18+
public init(store: ConvenienceStore, promotion: Promotion, order: Order, pageSize: Int, offset: Int) {
19+
self.store = store
20+
self.promotion = promotion
21+
self.order = order
22+
self.pageSize = pageSize
23+
self.offset = offset
24+
}
1725
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// ProductCountResponse.swift
3+
//
4+
//
5+
// Created by 홍승현 on 2/2/24.
6+
//
7+
8+
import Foundation
9+
10+
struct ProductCountResponse: Decodable {
11+
let count: Int
12+
}

APIService/Sources/HomeAPI/Responses/ProductResponse.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
import Entity
99
import Foundation
1010

11-
public struct ProductResponse: Decodable {
12-
public let id: Int
13-
public let imageURL: URL
14-
public let price: Int
15-
public let name: String
16-
public let promotion: Promotion
17-
public let convenienceStore: ConvenienceStore
11+
struct ProductResponse: Decodable {
12+
let id: Int
13+
let imageURL: URL
14+
let price: Int
15+
let name: String
16+
let promotion: Promotion
17+
let convenienceStore: ConvenienceStore
1818

19-
public enum CodingKeys: String, CodingKey {
19+
enum CodingKeys: String, CodingKey {
2020
case id
2121
case imageURL = "image_url"
2222
case price

APIService/Sources/HomeAPISupport/HomeURLProtocol.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@
66
//
77

88
import Foundation
9+
import HomeAPI
910
import Network
1011

1112
public final class HomeURLProtocol: URLProtocol {
12-
private let fileName = "HomeProductResponse"
13+
private lazy var mockData: [String: Data?] = [
14+
HomeEndPoint.fetchProducts(
15+
.init(store: .gs25, promotion: .allItems, order: .normal, pageSize: 0, offset: 0)
16+
).path: loadMockData(fileName: "HomeProductResponse"),
17+
HomeEndPoint.fetchCount(
18+
.init(convenienceStore: .gs25)
19+
).path: loadMockData(fileName: "HomeProductCountResponse"),
20+
]
1321

1422
override public class func canInit(with _: URLRequest) -> Bool {
1523
true
@@ -21,8 +29,9 @@ public final class HomeURLProtocol: URLProtocol {
2129

2230
override public func startLoading() {
2331
defer { client?.urlProtocolDidFinishLoading(self) }
24-
if let data = loadMockData(fileName: fileName),
25-
let url = request.url,
32+
if let url = request.url,
33+
let mockData = mockData[url.path(percentEncoded: true)],
34+
let data = mockData,
2635
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil) {
2736
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
2837
client?.urlProtocol(self, didLoad: data)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"count": 24
3+
}

Core/Sources/Network/NetworkProvider.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// Created by 홍승현 on 1/25/24.
66
//
77

8-
import Combine
98
import Foundation
109

1110
// MARK: - NetworkProvider

PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductSorterView.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
import SwiftUI
99

1010
struct HomeProductSorterView: View {
11-
private let count: Int
12-
13-
init(count: Int) {
14-
self.count = count
15-
}
11+
@EnvironmentObject private var viewModel: HomeViewModel
12+
@State private var count: Int = 0
1613

1714
var body: some View {
1815
HStack {
@@ -24,6 +21,11 @@ struct HomeProductSorterView: View {
2421
}
2522
}
2623
.padding(.all, 8)
24+
.onAppear {
25+
Task {
26+
count = try await viewModel.fetchProductCounts()
27+
}
28+
}
2729
}
2830

2931
var productCountString: AttributedString {
@@ -36,7 +38,3 @@ struct HomeProductSorterView: View {
3638
return string
3739
}
3840
}
39-
40-
#Preview {
41-
HomeProductSorterView(count: 50)
42-
}

PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct HomeView: View {
1515
NavigationStack {
1616
VStack {
1717
HomeProductDetailSelectionView()
18-
HomeProductSorterView(count: 12)
18+
HomeProductSorterView()
1919
HomeProductListView()
2020
}
2121
.padding(.horizontal, Metrics.horizontal)

PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeViewModel.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ final class HomeViewModel: ObservableObject {
2121
}
2222

2323
func fetchProducts() async throws {
24-
try await products.append(contentsOf: service.fetchProductList())
24+
// TODO: View와 연결할 때 수정해야합니다.
25+
let request: ProductRequest = .init(
26+
store: .gs25,
27+
promotion: .buyOneGetOneFree,
28+
order: .normal,
29+
pageSize: 20,
30+
offset: 0
31+
)
32+
try await products.append(contentsOf: service.fetchProductList(request: request))
33+
}
34+
35+
func fetchProductCounts() async throws -> Int {
36+
// TODO: 편의점 선택 뷰를 구성할 때 수정해야합니다.
37+
try await service.fetchProductCount(request: .init(convenienceStore: .gs25))
2538
}
2639
}

0 commit comments

Comments
 (0)