Skip to content

Commit be55614

Browse files
authored
[NL-77]: 로또 결과 안내 화면 API 연동 (#57)
* [NL-77]: navigation bar tint color 가 이상하게 적용되던 버그 해결 * [NL-77]: 결과 안내 화면 API 연동
1 parent e73c251 commit be55614

17 files changed

+376
-146
lines changed

Common/Base/Sources/NavigationBar.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,20 @@ public final class NavigationBar: UIView {
5757
fatalError("init(coder:) has not been implemented")
5858
}
5959

60-
public override func tintColorDidChange() {
61-
super.tintColorDidChange()
62-
defaultTitleLabel.textColor = tintColor
63-
leftItemsSection.arrangedSubviews.forEach {
64-
$0.tintColor = tintColor
65-
}
66-
rightItemsSection.arrangedSubviews.forEach {
67-
$0.tintColor = tintColor
68-
}
69-
}
70-
60+
public func updateColor(_ color: UIColor) {
61+
defaultTitleLabel.textColor = color
62+
leftItemsSection.arrangedSubviews
63+
.compactMap { $0 as? NavigationBarItem }
64+
.forEach {
65+
$0.updateColor(color)
66+
}
67+
rightItemsSection.arrangedSubviews
68+
.compactMap { $0 as? NavigationBarItem }
69+
.forEach {
70+
$0.updateColor(color)
71+
}
72+
}
73+
7174
private func setupUI(with style: Style, height: CGFloat) {
7275
addSubview(contentStackView)
7376
contentStackView.snp.makeConstraints { make in

Common/Base/Sources/NavigationBarItem.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
import DesignSystem
99
import UIKit
1010

11-
public protocol NavigationBarItem: UIView {}
11+
public protocol NavigationBarItem: UIView {
12+
func updateColor(_ color: UIColor)
13+
}
14+
15+
extension NavigationBarItem {
16+
public func updateColor(_ color: UIColor) { }
17+
}
1218

1319
public final class NaivgationBarButtonItem: UIButton, NavigationBarItem {
1420

@@ -25,11 +31,10 @@ public final class NaivgationBarButtonItem: UIButton, NavigationBarItem {
2531
make.size.equalTo(24)
2632
}
2733
}
28-
29-
override public func tintColorDidChange() {
30-
super.tintColorDidChange()
31-
let image = image(for: .normal)?.withRenderingMode(.alwaysTemplate)
32-
setImage(image?.withTintColor(tintColor), for: .normal)
34+
35+
public func updateColor(_ color: UIColor) {
36+
let image = image(for: .normal)?.withTintColor(color, renderingMode: .alwaysOriginal)
37+
setImage(image, for: .normal)
3338
}
3439
}
3540

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// Numeric+.swift
3+
// Extension
4+
//
5+
// Created by ttozzi on 8/20/25.
6+
//
7+
8+
import Foundation
9+
10+
extension Numeric {
11+
public var formattedWithSeparator: String {
12+
let formatter = NumberFormatter()
13+
formatter.numberStyle = .decimal
14+
formatter.groupingSeparator = ","
15+
formatter.maximumFractionDigits = 0
16+
return formatter.string(for: self) ?? "\(self)"
17+
}
18+
}

Feature/Home/Sources/Home/HomeService.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import DIInjector
1010
import Foundation
1111
import NetworkCore
1212

13-
struct HomeService {
13+
final class HomeService {
1414

1515
@Injected private var userDataManager: UserDataManager
1616
@Injected private var networkProvider: NetworkProvider
1717
private var appVersion: String? {
1818
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
1919
}
20+
var round: Int?
2021

2122
func fetch() async throws -> [any HomeCellModel] {
2223
let name = self.userDataManager.user?.name ?? "" // TODO: 확인 필요
@@ -29,6 +30,7 @@ struct HomeService {
2930
let (lottoRecommendation, dailyFortunes) = try await (
3031
lottoRecommendationRequest, dailyFortunesRequest
3132
)
33+
self.round = lottoRecommendation.round
3234

3335
let recommendationCollectionViewCellModel: HomeRecommendationCollectionViewCellModel
3436
if let recommendationContent = lottoRecommendation.content {

Feature/Home/Sources/Home/HomeViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public final class HomeViewModel {
6464
Task { @MainActor in
6565
homeRouter.navigate(
6666
to: HomeRoute.lottoResult, how: .push(hidesBottomBarWhenPushed: true),
67-
with: [:])
67+
with: ["round": homeService.round as Any])
6868
}
6969
}
7070
}

Feature/Home/Sources/HomeAssembly.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public final class HomeAssembly: Assembly {
1616
container.register(RecommendationDetailService.self) { _ in
1717
return RecommendationDetailService()
1818
}
19+
container.register(LottoResultService.self) { _ in
20+
return LottoResultService()
21+
}
1922
container.register(HomeRouter.self) { _ in
2023
return HomeRouter()
2124
}

Feature/Home/Sources/HomeRouter.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ final class HomeRouter: Routable {
3131
viewModel: RecommendationDetailViewModel(
3232
shouldCreateRecommendation: shouldCreateRecommendation ?? true))
3333
},
34-
.lottoResult: { _ in
35-
return LottoResultViewController(viewModel: LottoResultViewModel())
34+
.lottoResult: { data in
35+
guard let round = data["round"] as? Int else {
36+
fatalError() // TODO: 안전하게 처리할 방법이 필요함
37+
}
38+
return LottoResultViewController(viewModel: LottoResultViewModel(round: round))
3639
},
3740
]
3841
}

Feature/Home/Sources/HomeTarget.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,16 @@ enum HomeTarget {
4343
var headers: [String: String]? { nil }
4444
let userID: String
4545
}
46+
47+
struct CheckLottoResult: BaseTargetType {
48+
49+
typealias Response = LottoResultDTO
50+
51+
var path: String { "users/\(userID)/lotto-recommendation/\(round)/check" }
52+
var httpTask: HTTPTask { .requestPlain }
53+
var httpMethod: HTTPMethod { .post }
54+
var headers: [String: String]? { nil }
55+
let userID: String
56+
let round: Int
57+
}
4658
}

Feature/Home/Sources/LottoResult/LottoResultInfoView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Lottie
1010
import UIKit
1111

1212
struct LottoResultInfoModel {
13+
let isWinner: Bool
1314
let roundText: String
1415
let title: String
1516
let desciprtion: String
@@ -43,6 +44,9 @@ final class LottoResultInfoView: UIView {
4344
}
4445

4546
func update(with model: LottoResultInfoModel) {
47+
confettiiiiViews.forEach {
48+
$0.isHidden = !model.isWinner
49+
}
4650
roundTextChip.update(text: model.roundText)
4751
titleLabel.styledText = model.title
4852
descriptionLabel.styledText = model.desciprtion
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//
2+
// LottoResultNumberView.swift
3+
// Home
4+
//
5+
// Created by ttozzi on 8/20/25.
6+
//
7+
8+
import Base
9+
import DesignSystem
10+
import UIKit
11+
import SwiftRichString
12+
13+
struct LottoResultNumberModel {
14+
let rankText: String?
15+
let winningNumbers: [Int]
16+
let bonusNumber: Int
17+
let recommendedNumbers: [Int]
18+
}
19+
20+
final class LottoResultNumberView: UIView {
21+
22+
private lazy var resultStackView = UIStackView().then {
23+
$0.axis = .vertical
24+
$0.spacing = 20
25+
}
26+
27+
override init(frame: CGRect) {
28+
super.init(frame: frame)
29+
setupUI()
30+
}
31+
32+
required init?(coder: NSCoder) {
33+
fatalError("init(coder:) has not been implemented")
34+
}
35+
36+
func update(with model: LottoResultNumberModel) {
37+
resultStackView.arrangedSubviews.forEach {
38+
$0.removeFromSuperview()
39+
}
40+
let winningNumbersView = makeWinningNumbersView(
41+
numbers: model.winningNumbers,
42+
bonusNumber: model.bonusNumber
43+
)
44+
resultStackView.addArrangedSubview(winningNumbersView)
45+
46+
let resultView = makeResultView(
47+
rankText: model.rankText,
48+
recommendedNumbers: model.recommendedNumbers,
49+
winningNumbers: model.winningNumbers
50+
)
51+
resultStackView.addArrangedSubview(resultView)
52+
}
53+
54+
private func setupUI() {
55+
addSubview(resultStackView)
56+
resultStackView.snp.makeConstraints { make in
57+
make.edges.equalToSuperview()
58+
}
59+
}
60+
61+
private func makeContainerStackView() -> UIStackView {
62+
return UIStackView().then {
63+
$0.axis = .horizontal
64+
$0.distribution = .equalSpacing
65+
$0.alignment = .center
66+
$0.isLayoutMarginsRelativeArrangement = true
67+
$0.layoutMargins = UIEdgeInsets(top: 16, left: 20, bottom: 16, right: 20)
68+
$0.backgroundColor = STColors.white.color
69+
$0.layer.cornerRadius = 30
70+
$0.clipsToBounds = true
71+
}
72+
}
73+
74+
private func makeWinningNumbersView(numbers: [Int], bonusNumber: Int) -> UIView {
75+
let stackView = makeContainerStackView()
76+
numbers.forEach { number in
77+
let ball = Ball()
78+
ball.number = String(number)
79+
stackView.addArrangedSubview(ball)
80+
ball.snp.makeConstraints { make in
81+
make.size.equalTo(32)
82+
}
83+
}
84+
85+
let plusView = UIImageView(image: STImages.resultPlus.image)
86+
plusView.snp.makeConstraints { make in
87+
make.size.equalTo(14)
88+
}
89+
stackView.addArrangedSubview(plusView)
90+
91+
let bonusBall = Ball()
92+
bonusBall.number = String(bonusNumber)
93+
stackView.addArrangedSubview(bonusBall)
94+
95+
stackView.snp.makeConstraints { make in
96+
make.height.equalTo(64)
97+
}
98+
return stackView
99+
}
100+
101+
private func makeResultView(
102+
rankText: String?,
103+
recommendedNumbers: [Int],
104+
winningNumbers: [Int]
105+
) -> UIView {
106+
let stackView = makeContainerStackView()
107+
108+
let rankView = UIView().then {
109+
$0.backgroundColor = STColors.primary2.color
110+
$0.layer.cornerRadius = 16
111+
$0.clipsToBounds = true
112+
}
113+
let rankLabel = UILabel().then {
114+
$0.style = Style {
115+
$0.font = DesignSystemFontFamily.Suit.extraBold.font(size: 12)
116+
$0.kerning = .point(-0.18)
117+
$0.color = STColors.white.color
118+
}
119+
$0.styledText = rankText
120+
}
121+
rankView.addSubview(rankLabel)
122+
rankLabel.snp.makeConstraints { make in
123+
make.center.equalToSuperview()
124+
}
125+
126+
stackView.addArrangedSubview(rankView)
127+
rankView.snp.makeConstraints { make in
128+
make.size.equalTo(32)
129+
}
130+
131+
let barView = UIImageView(image: STImages.resultBar.image)
132+
barView.snp.makeConstraints { make in
133+
make.size.equalTo(14)
134+
}
135+
stackView.addArrangedSubview(barView)
136+
137+
recommendedNumbers.forEach { number in
138+
let ball = Ball()
139+
ball.number = String(number)
140+
ball.isColored = winningNumbers.contains(number)
141+
stackView.addArrangedSubview(ball)
142+
ball.snp.makeConstraints { make in
143+
make.size.equalTo(32)
144+
}
145+
}
146+
147+
stackView.snp.makeConstraints { make in
148+
make.height.equalTo(64)
149+
}
150+
return stackView
151+
}
152+
}

0 commit comments

Comments
 (0)