Skip to content

Commit 4a75ab4

Browse files
committed
[Chore] #177 - 도메인 엔티티 변경에 따른 수정
1 parent f2811fd commit 4a75ab4

2 files changed

Lines changed: 70 additions & 61 deletions

File tree

Neki-iOS/Core/Sources/Auth/Sources/Presentation/Sources/Feature/TermsAgreementFeature.swift

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,22 @@ import os
1313
public struct TermsAgreementFeature {
1414
@ObservableState
1515
public struct State {
16-
var agreements: IdentifiedArrayOf<UserAgreement>
16+
var agreements: IdentifiedArrayOf<UserAgreement> = []
1717
var isAllAgreed: Bool { agreements.allSatisfy(\.isAgreed) }
18-
var isConfirmButtonEnabled: Bool { agreements.filter(\.isRequired).allSatisfy(\.isAgreed) }
18+
var isConfirmButtonEnabled: Bool { agreements.filter(\.term.isRequired).allSatisfy(\.isAgreed) }
1919
var isLoading: Bool = false
20-
21-
public init() {
22-
self.agreements = [
23-
UserAgreement(type: .serviceUsage),
24-
UserAgreement(type: .privacyPolicy),
25-
UserAgreement(type: .locationService)
26-
]
27-
}
2820
}
2921

3022
public enum Action: BindableAction {
3123
// View Actions
32-
case toggleAgreement(TermsType)
24+
case onAppear
25+
case toggleAgreement(UserAgreement)
3326
case toggleAllAgreements
3427
case confirmButtonTapped
35-
case termPageLinkTapped(TermsType)
28+
case termPageLinkTapped(UserAgreement)
3629

3730
// Internal Actions
31+
case fetchTermsResponse(Result<[Term], Error>)
3832
case agreeTermsResponse(Result<Void, Error>)
3933

4034
// Delegate Actions
@@ -52,24 +46,41 @@ public struct TermsAgreementFeature {
5246

5347
Reduce { (state: inout State, action: Action) -> Effect<Action> in
5448
switch action {
55-
case let .toggleAgreement(type):
56-
state.agreements[id: type.id]?.isAgreed.toggle()
49+
case .onAppear:
50+
state.isLoading = true
51+
return .run { send in
52+
await send(.fetchTermsResponse(Result { try await authClient.fetchTerms() }))
53+
}
54+
55+
case let .toggleAgreement(agreement):
56+
state.agreements[id: agreement.id]?.isAgreed.toggle()
5757
return .none
5858

5959
case .toggleAllAgreements:
6060
let shouldAgreeAll = state.isAllAgreed == false
61-
for type in TermsType.allCases { state.agreements[id: type.id]?.isAgreed = shouldAgreeAll }
61+
for id in state.agreements.ids { state.agreements[id: id]?.isAgreed = shouldAgreeAll }
6262
return .none
6363

6464
case .confirmButtonTapped:
6565
guard state.isConfirmButtonEnabled, state.isLoading == false else { return .none }
6666
state.isLoading = true
67-
let agreementsToSend: [TermAgreement] = state.agreements.map { (id: $0.id, agreed: $0.isAgreed) }
67+
let agreementsToSend = Array(state.agreements)
6868

6969
return .run { send in
7070
await send(.agreeTermsResponse(Result { try await authClient.agreeWithTerms(agreementsToSend) }))
7171
}
7272

73+
case let .fetchTermsResponse(.success(terms)):
74+
let userAgreements = terms.map { UserAgreement(term: $0) }
75+
state.agreements = IdentifiedArray(uniqueElements: userAgreements)
76+
state.isLoading = false
77+
return .none
78+
79+
case let .fetchTermsResponse(.failure(error)):
80+
state.isLoading = false
81+
Logger.presentation.error("Error occured while fetching terms: \(error)")
82+
return .none
83+
7384
case .agreeTermsResponse(.success):
7485
state.isLoading = false
7586
return .send(.didFinishOnboarding)
@@ -79,15 +90,9 @@ public struct TermsAgreementFeature {
7990
Logger.presentation.error("Error occured while agreeing to terms: \(error)")
8091
return .none
8192

82-
case let .termPageLinkTapped(type):
83-
let urlString: String
84-
switch type {
85-
case .serviceUsage: urlString = "https://lydian-tip-26b.notion.site/2ee0d9441db0807c8684ce3e2d4b8aca?source=copy_link"
86-
case .privacyPolicy: urlString = "https://lydian-tip-26b.notion.site/2ee0d9441db0807cb850f78145db6dd3?pvs=74"
87-
case .locationService: urlString = "https://lydian-tip-26b.notion.site/2ee0d9441db080b48223fb0b3263da08?pvs=74"
88-
}
93+
case let .termPageLinkTapped(agreement):
8994
return .run { _ in
90-
guard let url = URL(string: urlString) else { return }
95+
guard let url = agreement.term.termInformationURL else { return }
9196
await openURL(url)
9297
}
9398

Neki-iOS/Core/Sources/Auth/Sources/Presentation/Sources/View/TermsAgreementView.swift

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,38 @@ public struct TermsAgreementView: View {
1414
@Bindable var store: StoreOf<TermsAgreementFeature>
1515

1616
public var body: some View {
17-
VStack(alignment: .leading, spacing: 12) {
18-
Image(.iconGpicAgreement)
19-
.padding(.horizontal, 20)
20-
.padding(.top, 12)
21-
22-
terms
17+
ZStack {
18+
VStack(alignment: .leading, spacing: 12) {
19+
Image(.iconGpicAgreement)
20+
.padding(.horizontal, 20)
21+
.padding(.top, 12)
22+
23+
terms
24+
.padding(.horizontal, 20)
25+
26+
Spacer()
27+
28+
Button {
29+
store.send(.confirmButtonTapped)
30+
} label: {
31+
Text("다음으로")
32+
}
33+
.buttonStyle(.nekiCTA())
34+
.disabled(store.isConfirmButtonEnabled == false)
2335
.padding(.horizontal, 20)
24-
25-
Spacer()
26-
27-
Button {
28-
store.send(.confirmButtonTapped)
29-
} label: {
30-
Text("다음으로")
36+
3137
}
32-
.buttonStyle(.nekiCTA())
33-
.disabled(store.isConfirmButtonEnabled == false)
34-
.padding(.horizontal, 20)
3538

39+
if store.isLoading {
40+
LoadingView()
41+
}
3642
}
3743
.nekiToolbar {
3844
NekiToolBar.back { dismiss() }
3945
} center: {
4046
NekiToolBar.textCenter("이용약관")
4147
}
48+
.task { await store.send(.onAppear).finish() }
4249
}
4350

4451
private var terms: some View {
@@ -78,36 +85,34 @@ public struct TermsAgreementView: View {
7885
}
7986

8087
VStack(alignment: .leading, spacing: 0) {
81-
ForEach(TermsType.allCases) { type in
82-
HStack(alignment: .center, spacing: 0) {
88+
ForEach(store.agreements) { agreement in
89+
HStack(alignment: .center, spacing: .zero) {
8390
Button {
84-
store.send(.toggleAgreement(type))
91+
store.send(.toggleAgreement(agreement))
8592
} label: {
86-
HStack(alignment: .center, spacing: 0) {
87-
if let agreement = store.agreements[id: type.id] {
88-
Image(agreement.isAgreed ? .iconCheckmark : .iconCheckmarkGray)
89-
.frame(width: 44, height: 44)
90-
.scaledToFit()
93+
HStack(alignment: .center, spacing: .zero) {
94+
Image(agreement.isAgreed ? .iconCheckmark : .iconCheckmarkGray)
95+
.frame(width: 44, height: 44)
96+
.scaledToFit()
97+
98+
HStack(alignment: .center, spacing: 2) {
99+
Text(agreement.term.isRequired ? "(필수)" : "(선택)")
100+
.nekiFont(.body14Medium)
101+
.foregroundStyle(.gray500)
91102

92-
HStack(alignment: .center, spacing: 2) {
93-
Text(agreement.isRequired ? "(필수)" : "(선택)")
94-
.nekiFont(.body14Medium)
95-
.foregroundStyle(.gray500)
96-
97-
Text(type.displayName)
98-
.nekiFont(.body16Medium)
99-
.foregroundStyle(.gray900)
100-
.frame(maxWidth: .infinity, alignment: .leading)
101-
.padding(.vertical)
102-
}
103+
Text(agreement.term.title)
104+
.nekiFont(.body16Medium)
105+
.foregroundStyle(.gray900)
106+
.frame(maxWidth: .infinity, alignment: .leading)
107+
.padding(.vertical)
103108
}
104109
}
105110
}
106111

107112
Spacer()
108113

109114
Button {
110-
store.send(.termPageLinkTapped(type))
115+
store.send(.termPageLinkTapped(agreement))
111116
} label: {
112117
Image(.iconChevronRight)
113118
.resizable()
@@ -116,7 +121,6 @@ public struct TermsAgreementView: View {
116121
}
117122
}
118123
}
119-
120124
}
121125
}
122126
}

0 commit comments

Comments
 (0)