Skip to content

Commit 9aca4aa

Browse files
authored
Merge pull request #185 from YAPP-Github/feat/#180-recommend
feat: [2.0.0] 버전 업데이트에 따른 기능 추가 및 수정(링크 추천)
2 parents dbcbb18 + a2ce3f0 commit 9aca4aa

File tree

35 files changed

+883
-739
lines changed

35 files changed

+883
-739
lines changed

Projects/App/Sources/MainTab/MainTab.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import DSKit
1111

1212
public enum MainTab: String, CaseIterable {
1313
case pokit = "포킷"
14-
case remind = "리마인드"
14+
case recommend = "링크추천"
1515

1616
var title: String { return self.rawValue }
1717

1818
var icon: PokitImage {
1919
switch self {
2020
case .pokit: return .icon(.folderFill)
21-
case .remind: return .icon(.remind)
21+
case .recommend: return .icon(.remind)
2222
}
2323
}
2424
}

Projects/App/Sources/MainTab/MainTabFeature.swift

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

99
import ComposableArchitecture
1010
import FeaturePokit
11-
import FeatureRemind
11+
import FeatureRecommend
1212
import FeatureContentDetail
1313
import Domain
1414
import DSKit
@@ -37,7 +37,7 @@ public struct MainTabFeature {
3737

3838
var path: StackState<MainTabPath.State> = .init()
3939
var pokit: PokitRootFeature.State
40-
var remind: RemindFeature.State = .init()
40+
var recommend: RecommendFeature.State = .init()
4141
@Presents var contentDetail: ContentDetailFeature.State?
4242
@Shared(.inMemory("SelectCategory")) var categoryId: Int?
4343
@Shared(.inMemory("PushTapped")) var isPushTapped: Bool = false
@@ -59,7 +59,7 @@ public struct MainTabFeature {
5959
/// Todo: scope로 이동
6060
case path(StackAction<MainTabPath.State, MainTabPath.Action>)
6161
case pokit(PokitRootFeature.Action)
62-
case remind(RemindFeature.Action)
62+
case recommend(RecommendFeature.Action)
6363
case contentDetail(PresentationAction<ContentDetailFeature.Action>)
6464

6565
@CasePathable
@@ -70,6 +70,8 @@ public struct MainTabFeature {
7070
case onAppear
7171
case onOpenURL(url: URL)
7272
case 경고_확인버튼_클릭
73+
case 검색_버튼_눌렀을때
74+
case 알림_버튼_눌렀을때
7375
}
7476
public enum InnerAction: Equatable {
7577
case 링크추가및수정이동(contentId: Int)
@@ -129,7 +131,7 @@ public struct MainTabFeature {
129131
return .none
130132
case .pokit:
131133
return .none
132-
case .remind:
134+
case .recommend:
133135
return .none
134136
case .contentDetail:
135137
return .none
@@ -138,7 +140,14 @@ public struct MainTabFeature {
138140
/// - Reducer body
139141
public var body: some ReducerOf<Self> {
140142
Scope(state: \.pokit, action: \.pokit) { PokitRootFeature() }
141-
Scope(state: \.remind, action: \.remind) { RemindFeature() }
143+
Scope(state: \.recommend, action: \.recommend) {
144+
withDependencies {
145+
$0[UserClient.self] = .testValue
146+
$0[ContentClient.self] = .testValue
147+
} operation: {
148+
RecommendFeature()
149+
}
150+
}
142151

143152
BindingReducer()
144153
navigationReducer
@@ -198,6 +207,28 @@ private extension MainTabFeature {
198207
case .경고_확인버튼_클릭:
199208
state.error = nil
200209
return .run { send in await send(.inner(.errorSheetPresented(false))) }
210+
case .검색_버튼_눌렀을때:
211+
switch state.selectedTab {
212+
case .pokit: return .none
213+
case .recommend:
214+
return RecommendFeature()
215+
.reduce(
216+
into: &state.recommend,
217+
action: .view(.검색_버튼_눌렀을때)
218+
)
219+
.map(Action.recommend)
220+
}
221+
case .알림_버튼_눌렀을때:
222+
switch state.selectedTab {
223+
case .pokit: return .none
224+
case .recommend:
225+
return RecommendFeature()
226+
.reduce(
227+
into: &state.recommend,
228+
action: .view(.알림_버튼_눌렀을때)
229+
)
230+
.map(Action.recommend)
231+
}
201232
}
202233
}
203234
/// - Inner Effect

Projects/App/Sources/MainTab/MainTabFeatureView.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import SwiftUI
99
import ComposableArchitecture
1010
import DSKit
1111
import FeaturePokit
12-
import FeatureRemind
12+
import FeatureRecommend
1313
import FeatureSetting
1414
import FeatureCategorySetting
1515
import FeatureContentDetail
@@ -135,8 +135,8 @@ private extension MainTabView {
135135
.pokitNavigationBar { pokitNavigationBar }
136136
.toolbarBackground(.hidden, for: .tabBar)
137137

138-
case .remind:
139-
RemindView(store: store.scope(state: \.remind, action: \.remind))
138+
case .recommend:
139+
RecommendView(store: store.scope(state: \.recommend, action: \.recommend))
140140
.pokitNavigationBar { remindNavigationBar }
141141
.toolbarBackground(.hidden, for: .tabBar)
142142
}
@@ -173,19 +173,19 @@ private extension MainTabView {
173173
var remindNavigationBar: some View {
174174
PokitHeader {
175175
PokitHeaderItems(placement: .leading) {
176-
Text("Remind")
177-
.font(.system(size: 32, weight: .heavy))
178-
.foregroundStyle(.pokit(.text(.brand)))
176+
Text("링크추천")
177+
.pokitFont(.title2)
178+
.foregroundStyle(.pokit(.text(.primary)))
179179
}
180180

181181
PokitHeaderItems(placement: .trailing) {
182182
PokitToolbarButton(
183183
.icon(.search),
184-
action: { store.send(.remind(.view(.검색_버튼_눌렀을때))) }
184+
action: { send(.검색_버튼_눌렀을때) }
185185
)
186186
PokitToolbarButton(
187187
.icon(.bell),
188-
action: { store.send(.remind(.view(.알림_버튼_눌렀을때))) }
188+
action: { send(.알림_버튼_눌렀을때) }
189189
)
190190
}
191191
}
@@ -198,7 +198,7 @@ private extension MainTabView {
198198

199199
Spacer()
200200

201-
bottomTabBarItem(.remind)
201+
bottomTabBarItem(.recommend)
202202
}
203203
.padding(.horizontal, 48)
204204
.padding(.top, 12)

Projects/App/Sources/MainTab/MainTabPath.swift

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ public extension MainTabFeature {
6161
switch action {
6262
/// - 네비게이션 바 `알림`버튼 눌렀을 때
6363
case .pokit(.delegate(.alertButtonTapped)),
64-
.remind(.delegate(.alertButtonTapped)),
64+
.recommend(.delegate(.알림_버튼_눌렀을때)),
6565
.delegate(.알림함이동):
6666
state.isPushTapped = false
6767
state.path.append(.알림함(PokitAlertBoxFeature.State()))
6868
return .none
6969

7070
/// - 네비게이션 바 `검색`버튼 눌렀을 때
7171
case .pokit(.delegate(.searchButtonTapped)),
72-
.remind(.delegate(.searchButtonTapped)):
72+
.recommend(.delegate(.검색_버튼_눌렀을때)):
7373
state.path.append(.검색(PokitSearchFeature.State()))
7474
return .none
7575

@@ -118,7 +118,6 @@ public extension MainTabFeature {
118118
/// - 링크 상세
119119
case let .path(.element(_, action: .카테고리상세(.delegate(.contentItemTapped(content))))),
120120
let .pokit(.delegate(.contentDetailTapped(content))),
121-
let .remind(.delegate(.링크상세(content))),
122121
let .path(.element(_, action: .링크목록(.delegate(.링크상세(content: content))))),
123122
let .path(.element(_, action: .검색(.delegate(.linkCardTapped(content: content))))):
124123

@@ -128,7 +127,7 @@ public extension MainTabFeature {
128127
/// - 링크상세 바텀시트에서 링크수정으로 이동
129128
case let .contentDetail(.presented(.delegate(.editButtonTapped(id)))),
130129
let .pokit(.delegate(.링크수정하기(id))),
131-
let .remind(.delegate(.링크수정(id))),
130+
let .recommend(.delegate(.추가하기_버튼_눌렀을때(id))),
132131
let .path(.element(_, action: .카테고리상세(.delegate(.링크수정(id))))),
133132
let .path(.element(_, action: .링크목록(.delegate(.링크수정(id))))),
134133
let .path(.element(_, action: .검색(.delegate(.링크수정(id))))),
@@ -146,8 +145,8 @@ public extension MainTabFeature {
146145
switch state.selectedTab {
147146
case .pokit:
148147
return .send(.pokit(.delegate(.미분류_카테고리_컨텐츠_조회)))
149-
case .remind:
150-
return .send(.remind(.delegate(.컨텐츠_상세보기_delegate_위임)))
148+
case .recommend:
149+
return .none
151150
}
152151
}
153152
switch lastPath {
@@ -198,14 +197,6 @@ public extension MainTabFeature {
198197
case let .pokit(.delegate(.linkPopup(text))):
199198
state.linkPopup = .text(title: text)
200199
return .none
201-
/// 링크목록 `안읽음`
202-
case .remind(.delegate(.링크목록_안읽음)):
203-
state.path.append(.링크목록(ContentListFeature.State(contentType: .unread)))
204-
return .none
205-
/// 링크목록 `즐겨찾기`
206-
case .remind(.delegate(.링크목록_즐겨찾기)):
207-
state.path.append(.링크목록(ContentListFeature.State(contentType: .favorite)))
208-
return .none
209200

210201
case .path(.element(_, action: .설정(.delegate(.로그아웃)))):
211202
return .send(.delegate(.로그아웃))

Projects/CoreKit/Sources/Data/DTO/Base/ContentBaseResponse.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,26 @@ public struct ContentBaseResponse: Decodable {
1818
public let createdAt: String
1919
public let isRead: Bool?
2020
public let isFavorite: Bool?
21+
public let keyword: String?
2122
}
2223

2324
extension ContentBaseResponse {
2425
public static func mock(id: Int) -> Self {
2526
Self(
2627
contentId: id,
2728
category: .init(
28-
categoryId: 992,
29-
categoryName: "미분류"
29+
categoryId: 567,
30+
categoryName: "신서유기"
3031
),
31-
data: "https://www.youtube.com/watch?v=wtSwdGJzQCQ",
32+
data: "https://youtu.be/CIzKDrN7IpU?si=B0-7X7I_54VHAfkk",
3233
domain: "youtube",
33-
title: "신서유기",
34+
title: "[#샷추가] 거리 두기 철저하게 지키게 만드는 인물 퀴즈ㅋㅋㅋ어떤 음식을 뺄지 고민하지 마요..어차피 다 못 먹으니까요🤣 | #신서유기5 #Diggle",
3435
memo: nil,
35-
thumbNail: "https://i.ytimg.com/vi/NnOC4_kH0ok/hqdefault.jpg?sqp=-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE=&rs=AOn4CLDN6u6mTjbaVmRZ4biJS_aDq4uvAQ",
36-
createdAt: "2024.08.08",
36+
thumbNail: "https://i.ytimg.com/vi/CIzKDrN7IpU/maxresdefault.jpg",
37+
createdAt: "2024.12.03",
3738
isRead: false,
38-
isFavorite: true
39+
isFavorite: true,
40+
keyword: "예능"
3941
)
4042
}
4143
}

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/CoreKit/Sources/Data/Network/Content/ContentClient+LiveKey.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ extension ContentClient: DependencyKey {
6161
},
6262
미분류_링크_삭제: { model in
6363
try await provider.requestNoBody(.미분류_링크_삭제(model: model))
64+
},
65+
추천_컨텐츠_조회: { pageable, keyword in
66+
try await provider.request(.추천_컨텐츠_조회(pageable: pageable, keyword: keyword))
6467
}
6568
)
6669
}()

Projects/CoreKit/Sources/Data/Network/Content/ContentClient+TestKey.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ extension ContentClient: TestDependencyKey {
2020
컨텐츠_검색: { _, _ in .mock },
2121
썸네일_수정: { _, _ in },
2222
미분류_링크_포킷_이동: { _ in },
23-
미분류_링크_삭제: { _ in }
23+
미분류_링크_삭제: { _ in },
24+
추천_컨텐츠_조회: { _, _ in .mock }
2425
)
2526
}()
2627
}

Projects/CoreKit/Sources/Data/Network/Content/ContentClient.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,9 @@ public struct ContentClient {
5050
public var 미분류_링크_삭제: @Sendable (
5151
_ model: ContentDeleteRequest
5252
) async throws -> Void
53+
public var 추천_컨텐츠_조회: @Sendable (
54+
_ pageable: BasePageableRequest,
55+
_ keyword: String?
56+
) async throws -> ContentListInquiryResponse
5357
}
5458

Projects/CoreKit/Sources/Data/Network/Content/ContentEndpoint.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public enum ContentEndpoint {
3030
case 썸네일_수정(contentId: String, model: ThumbnailRequest)
3131
case 미분류_링크_포킷_이동(model: ContentMoveRequest)
3232
case 미분류_링크_삭제(model: ContentDeleteRequest)
33+
case 추천_컨텐츠_조회(
34+
pageable: BasePageableRequest,
35+
keyword: String?
36+
)
3337
}
3438

3539
extension ContentEndpoint: TargetType {
@@ -63,6 +67,8 @@ extension ContentEndpoint: TargetType {
6367
return ""
6468
case .미분류_링크_삭제:
6569
return "/uncategorized"
70+
case .추천_컨텐츠_조회:
71+
return "/recommended"
6672
}
6773
}
6874

@@ -85,7 +91,8 @@ extension ContentEndpoint: TargetType {
8591

8692
case .카태고리_내_컨텐츠_목록_조회,
8793
.미분류_카테고리_컨텐츠_조회,
88-
.컨텐츠_검색:
94+
.컨텐츠_검색,
95+
.추천_컨텐츠_조회:
8996
return .get
9097
}
9198
}
@@ -126,6 +133,19 @@ extension ContentEndpoint: TargetType {
126133
],
127134
encoding: URLEncoding.default
128135
)
136+
case let .추천_컨텐츠_조회(pageable, keyword):
137+
var parameters: [String: Any] = [
138+
"page": pageable.page,
139+
"size": pageable.size,
140+
"sort": pageable.sort.map { String($0) }.joined(separator: ",")
141+
]
142+
if let keyword {
143+
parameters["keyword"] = keyword
144+
}
145+
return .requestParameters(
146+
parameters: parameters,
147+
encoding: URLEncoding.default
148+
)
129149
case let .컨텐츠_검색(pageable, condition):
130150
return .requestParameters(
131151
parameters: [

0 commit comments

Comments
 (0)