Skip to content

Commit ec6e019

Browse files
committed
[feat] #180 관심사 필터링 기능 구현
1 parent 1e165ab commit ec6e019

4 files changed

Lines changed: 100 additions & 30 deletions

File tree

Projects/CoreKit/Sources/Data/DTO/User/InterestResponse.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ extension InterestResponse {
2323
Self(code: "code2", description: "산책"),
2424
Self(code: "code3", description: "프로그래밍"),
2525
Self(code: "code4", description: "여행"),
26-
Self(code: "code5", description: "요리")
26+
Self(code: "code5", description: "요리"),
27+
Self(code: "code6", description: "스포츠/레저"),
28+
Self(code: "code7", description: "기획/마케팅"),
29+
Self(code: "code8", description: "쇼핑"),
30+
Self(code: "code9", description: "경제/시사"),
31+
Self(code: "code10", description: "영화/드라마"),
32+
Self(code: "code11", description: "장소"),
33+
Self(code: "code12", description: "인테리어"),
34+
Self(code: "code13", description: "IT"),
2735
]
2836
}

Projects/DSKit/Sources/Components/PokitTextButton.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public struct PokitTextButton: View {
4141
.foregroundStyle(self.state.textColor)
4242
.padding(.horizontal, self.size.hPadding)
4343
.padding(.vertical, self.size.vPadding)
44+
.frame(minWidth: self.size.minWidth)
4445
.background {
4546
RoundedRectangle(cornerRadius: shape.radius(size: self.size), style: .continuous)
4647
.fill(self.state.backgroundColor)
@@ -49,6 +50,5 @@ public struct PokitTextButton: View {
4950
.stroke(self.state.backgroundStrokeColor, lineWidth: 1)
5051
}
5152
}
52-
.frame(minWidth: self.size.minWidth)
5353
}
5454
}

Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendFeature.swift

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//
55
// Created by 김도형 on 1/29/25.
66

7+
import SwiftUI
8+
79
import ComposableArchitecture
810
import Domain
911
import CoreKit
@@ -14,6 +16,8 @@ public struct RecommendFeature {
1416
/// - Dependency
1517
@Dependency(ContentClient.self)
1618
private var contentClient
19+
@Dependency(UserClient.self)
20+
private var userClient
1721
@Dependency(PasteboardClient.self)
1822
private var pasteBoard
1923
/// - State
@@ -33,7 +37,13 @@ public struct RecommendFeature {
3337
array.append(contentsOf: list)
3438
return array
3539
}
40+
var interestList: IdentifiedArrayOf<BaseInterest> {
41+
var array = IdentifiedArrayOf<BaseInterest>()
42+
array.append(contentsOf: domain.interests)
43+
return array
44+
}
3645
var isLoading: Bool = true
46+
var selectedInterest: BaseInterest?
3747
}
3848

3949
/// - Action
@@ -45,10 +55,12 @@ public struct RecommendFeature {
4555
case delegate(DelegateAction)
4656

4757
@CasePathable
48-
public enum View: Equatable {
58+
public enum View {
4959
case 추가하기_버튼_눌렀을때(BaseContentItem)
5060
case 공유하기_버튼_눌렀을때(BaseContentItem)
5161
case 신고하기_버튼_눌렀을때(BaseContentItem)
62+
case 전체보기_버튼_눌렀을때(ScrollViewProxy)
63+
case 관심사_버튼_눌렀을때(BaseInterest, ScrollViewProxy)
5264

5365
case onAppear
5466
case pagination
@@ -57,11 +69,13 @@ public struct RecommendFeature {
5769
public enum InnerAction: Equatable {
5870
case 추천_조회_API_반영(BaseContentListInquiry)
5971
case 추천_조회_페이징_API_반영(BaseContentListInquiry)
72+
case 유저_관심사_조회_API_반영([BaseInterest])
6073
}
6174

6275
public enum AsyncAction: Equatable {
6376
case 추천_조회_API
6477
case 추천_조회_페이징_API
78+
case 유저_관심사_조회_API
6579
}
6680

6781
public enum ScopeAction: Equatable { case doNothing }
@@ -108,7 +122,10 @@ private extension RecommendFeature {
108122
func handleViewAction(_ action: Action.View, state: inout State) -> Effect<Action> {
109123
switch action {
110124
case .onAppear:
111-
return shared(.async(.추천_조회_API), state: &state)
125+
return .merge(
126+
shared(.async(.추천_조회_API), state: &state),
127+
shared(.async(.유저_관심사_조회_API), state: &state)
128+
)
112129
case .pagination:
113130
return shared(.async(.추천_조회_페이징_API), state: &state)
114131
case let .추가하기_버튼_눌렀을때(content):
@@ -117,6 +134,18 @@ private extension RecommendFeature {
117134
return .none
118135
case let .신고하기_버튼_눌렀을때(content):
119136
return .none
137+
case let .전체보기_버튼_눌렀을때(proxy):
138+
guard state.selectedInterest != nil else { return .none }
139+
140+
state.selectedInterest = nil
141+
proxy.scrollTo("전체보기", anchor: .leading)
142+
return shared(.async(.추천_조회_API), state: &state)
143+
case let .관심사_버튼_눌렀을때(interest, proxy):
144+
guard state.selectedInterest != interest else { return .none }
145+
146+
state.selectedInterest = interest
147+
proxy.scrollTo(interest.description, anchor: .leading)
148+
return shared(.async(.추천_조회_API), state: &state)
120149
}
121150
}
122151

@@ -135,6 +164,9 @@ private extension RecommendFeature {
135164

136165
state.isLoading = false
137166
return .none
167+
case let .유저_관심사_조회_API_반영(interests):
168+
state.domain.interests = interests
169+
return .none
138170
}
139171
}
140172

@@ -148,16 +180,23 @@ private extension RecommendFeature {
148180
page: state.domain.pageable.page,
149181
size: state.domain.pageable.size,
150182
sort: state.domain.pageable.sort
151-
)
183+
),
184+
keyword = state.selectedInterest?.description
152185
] send in
153186
let contentList = try await contentClient.추천_컨텐츠_조회(
154-
model: pageableRequest
187+
pageable: pageableRequest,
188+
keyword: keyword
155189
).toDomain()
156190

157191
await send(.inner(.추천_조회_페이징_API_반영(contentList)))
158192
}
159193
case .추천_조회_API:
160194
return contentListFetch(state: &state)
195+
case .유저_관심사_조회_API:
196+
return .run { send in
197+
let interests = try await userClient.유저_관심사_목록_조회().map { $0.toDomian() }
198+
await send(.inner(.유저_관심사_조회_API_반영(interests)))
199+
}
161200
}
162201
}
163202

@@ -189,7 +228,8 @@ private extension RecommendFeature {
189228

190229
func contentListFetch(state: inout State) -> Effect<Action> {
191230
return .run { [
192-
pageable = state.domain.pageable
231+
pageable = state.domain.pageable,
232+
keyword = state.selectedInterest?.description
193233
] send in
194234
let stream = AsyncThrowingStream<BaseContentListInquiry, Error> { continuation in
195235
Task {
@@ -200,7 +240,8 @@ private extension RecommendFeature {
200240
sort: pageable.sort
201241
)
202242
let contentList = try await contentClient.추천_컨텐츠_조회(
203-
model: pageableRequest
243+
pageable: pageableRequest,
244+
keyword: keyword
204245
).toDomain()
205246
continuation.yield(contentList)
206247
}

Projects/Feature/FeatureRecommend/Sources/Recommend/RecommendView.swift

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,54 @@ public extension RecommendView {
3939
//MARK: - Configure View
4040
private extension RecommendView {
4141
var interestList: some View {
42-
ScrollView(.horizontal) {
43-
HStack(spacing: 8) {
44-
PokitTextButton(
45-
"전체보기",
46-
state: .filled(.primary),
47-
size: .small,
48-
shape: .round,
49-
action: { }
42+
ScrollViewReader { proxy in
43+
ScrollView(.horizontal, showsIndicators: false) {
44+
interestListContent(proxy)
45+
.padding(.horizontal, 20)
46+
.padding(.top, 8)
47+
.padding(.bottom, 12)
48+
}
49+
}
50+
}
51+
52+
@ViewBuilder
53+
func interestListContent(_ proxy: ScrollViewProxy) -> some View {
54+
HStack(spacing: 8) {
55+
let isAllSelected = store.selectedInterest == nil
56+
57+
PokitTextButton(
58+
"전체보기",
59+
state: isAllSelected
60+
? .filled(.primary)
61+
: .default(.secondary),
62+
size: .small,
63+
shape: .round
64+
) {
65+
send(
66+
.전체보기_버튼_눌렀을때(proxy),
67+
animation: .pokitDissolve
5068
)
69+
}
70+
.id("전체보기")
71+
72+
ForEach(store.interestList) { interest in
73+
let isSelected = store.selectedInterest == interest
5174

52-
ForEach(store.interestList) { interest in
53-
let isSelected = store.selectedInterest == interest
54-
55-
PokitTextButton(
56-
interest.description,
57-
state: isSelected
58-
? .filled(.primary)
59-
: .default(.secondary),
60-
size: .small,
61-
shape: .round,
62-
action: { }
75+
PokitTextButton(
76+
interest.description,
77+
state: isSelected
78+
? .filled(.primary)
79+
: .default(.secondary),
80+
size: .small,
81+
shape: .round
82+
) {
83+
send(
84+
.관심사_버튼_눌렀을때(interest, proxy),
85+
animation: .pokitDissolve
6386
)
6487
}
88+
.id(interest.description)
6589
}
66-
.padding(.horizontal, 20)
67-
.padding(.top, 8)
68-
.padding(.bottom, 12)
6990
}
7091
}
7192

0 commit comments

Comments
 (0)