Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.0.0] 검색 도메인 네비게이션 작업 #60

Merged
merged 11 commits into from
Nov 26, 2023
4 changes: 4 additions & 0 deletions KuringApp/KuringApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
CAD5A42B2B10750800DED0D5 /* DepartmentSelectorLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A42A2B10750800DED0D5 /* DepartmentSelectorLink.swift */; };
CAD5A42D2B1077C200DED0D5 /* NoticeContentView.NoDepartment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A42C2B1077C200DED0D5 /* NoticeContentView.NoDepartment.swift */; };
CAD5A42F2B11DBAF00DED0D5 /* NoticeList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A42E2B11DBAF00DED0D5 /* NoticeList.swift */; };
CAD5A4312B121B2F00DED0D5 /* StaffDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A4302B121B2F00DED0D5 /* StaffDetail.swift */; };
DF331DAB2AC917E100D0BB08 /* kuring_app.png in Resources */ = {isa = PBXBuildFile; fileRef = DF331DA72AC917E000D0BB08 /* kuring_app.png */; };
DF331DAC2AC917E100D0BB08 /* kuring_app_classic.png in Resources */ = {isa = PBXBuildFile; fileRef = DF331DA82AC917E000D0BB08 /* kuring_app_classic.png */; };
DF331DAD2AC917E100D0BB08 /* kuring_app_sketch.png in Resources */ = {isa = PBXBuildFile; fileRef = DF331DA92AC917E000D0BB08 /* kuring_app_sketch.png */; };
Expand Down Expand Up @@ -88,6 +89,7 @@
CAD5A42A2B10750800DED0D5 /* DepartmentSelectorLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DepartmentSelectorLink.swift; sourceTree = "<group>"; };
CAD5A42C2B1077C200DED0D5 /* NoticeContentView.NoDepartment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeContentView.NoDepartment.swift; sourceTree = "<group>"; };
CAD5A42E2B11DBAF00DED0D5 /* NoticeList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeList.swift; sourceTree = "<group>"; };
CAD5A4302B121B2F00DED0D5 /* StaffDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaffDetail.swift; sourceTree = "<group>"; };
DF062D4A2AC87B6D00FC48C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
DF331DA72AC917E000D0BB08 /* kuring_app.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = kuring_app.png; sourceTree = "<group>"; };
DF331DA82AC917E000D0BB08 /* kuring_app_classic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = kuring_app_classic.png; sourceTree = "<group>"; };
Expand Down Expand Up @@ -162,6 +164,7 @@
isa = PBXGroup;
children = (
A9B4F01C2ABCB4CE00354C00 /* SearchView.swift */,
CAD5A4302B121B2F00DED0D5 /* StaffDetail.swift */,
B11DBDCB2ACB370500501CA8 /* StaffRow.swift */,
);
path = Search;
Expand Down Expand Up @@ -402,6 +405,7 @@
A9B4F0162ABCA93400354C00 /* NoticeApp.Path.swift in Sources */,
CAD5A42B2B10750800DED0D5 /* DepartmentSelectorLink.swift in Sources */,
A9B4F0182ABCA9AF00354C00 /* NoticeDetailView.swift in Sources */,
CAD5A4312B121B2F00DED0D5 /* StaffDetail.swift in Sources */,
CAD5A4292B10724100DED0D5 /* NoticeTypeColumn.swift in Sources */,
B1CBFA662AC7113C00C1E0ED /* NoticeRow.swift in Sources */,
A965B7AF2AC084D20026ECDC /* SubscriptionApp.swift in Sources */,
Expand Down
13 changes: 9 additions & 4 deletions KuringApp/KuringApp/NoticeApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,19 @@ struct NoticeAppView: View {
action: { .noticeList($0) }
)
)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItemGroup(placement: .navigationBarLeading) {
Image("appIconLabel", bundle: Bundle.noticeList)
}

ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
// TODO: - to SearchView
} label: {
// MARK: 검색창 진입
NavigationLink(
state: NoticeAppFeature.Path.State.search(
SearchFeature.State()
)
) {
Image(systemName: "magnifyingglass")
.foregroundStyle(Color.black)
}
Expand Down Expand Up @@ -146,7 +150,8 @@ struct NoticeAppView: View {
action: NoticeAppFeature.Path.Action.search
) { store in
SearchView(store: store)
.navigationTitle("Search View")
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("검색하기")
}

case .departmentEditor:
Expand Down
4 changes: 2 additions & 2 deletions KuringApp/KuringApp/NoticeList/NoticeDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ struct NoticeDetailFeature: Reducer {
var isBookmarked: Bool = false
}

enum Action {
enum Action: Equatable {
case bookmarkButtonTapped

case delegate(Delegate)

enum Delegate {
enum Delegate: Equatable {
case bookmarkUpdated(Bool)
}
}
Expand Down
53 changes: 44 additions & 9 deletions KuringApp/KuringApp/Search/SearchView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import ComposableArchitecture

struct SearchFeature: Reducer {
struct State: Equatable {
@PresentationState var staffDetail: StaffDetailFeature.State?

var recents: [String] = []

var resultNotices: [Notice]? = nil
Expand Down Expand Up @@ -48,6 +50,8 @@ struct SearchFeature: Reducer {
}

enum Action: BindableAction {
/// 트리 네비게이션 - ``StaffDetailFeature`` 액션
case staffDetail(PresentationAction<StaffDetailFeature.Action>)
/// 최근 검색어 전체 삭제
case deleteAllRecentsButtonTapped
/// 검색어 제거
Expand All @@ -58,6 +62,8 @@ struct SearchFeature: Reducer {
case searchResponse(Result<SearchResult, SearchError>)
/// 최근 검색어 선택. associated value 는 최근 검색어.
case recentSearchKeywordTapped(String)
/// ``StaffRow`` 선택
case staffRowSelected(Staff)

case binding(BindingAction<State>)

Expand Down Expand Up @@ -145,8 +151,22 @@ struct SearchFeature: Reducer {
}
state.searchInfo.searchPhase = .failure
return .none

case let .staffRowSelected(staff):
state.staffDetail = StaffDetailFeature.State(staff: staff)
return .none

case .staffDetail(.dismiss):
state.staffDetail = nil
return .none

case .staffDetail:
return .none
}
}
.ifLet(\.$staffDetail, action: /Action.staffDetail) {
StaffDetailFeature()
}
}
}

Expand Down Expand Up @@ -182,7 +202,7 @@ struct SearchView: View {
.frame(width: 16, height: 16)
.foregroundStyle(Color(red: 0.21, green: 0.24, blue: 0.29).opacity(0.6))
}
}
}
}
}
.padding(.horizontal, 16)
Expand Down Expand Up @@ -277,13 +297,19 @@ struct SearchView: View {
case .notice:
if let notices = viewStore.resultNotices, !notices.isEmpty {
List(notices, id: \.self) { notice in
VStack(alignment: .leading) {
Text(notice.subject)

HStack {
Text(notice.postedDate)

Spacer()
NavigationLink(
state: NoticeAppFeature.Path.State.detail(
NoticeDetailFeature.State(notice: notice)
)
) {
VStack(alignment: .leading) {
Text(notice.subject)

HStack {
Text(notice.postedDate)

Spacer()
}
}
}
}
Expand All @@ -295,7 +321,7 @@ struct SearchView: View {
if let staffs = viewStore.resultStaffs, !staffs.isEmpty {
List(staffs, id: \.self) { staff in
Button {
// TODO: - 프레젠트 액션 연결하기
viewStore.send(.staffRowSelected(staff))
} label: {
StaffRow(staff: staff)
}
Expand All @@ -311,6 +337,15 @@ struct SearchView: View {
.padding(.horizontal, 20)
.bind(viewStore.$focus, to: self.$focus)
}
.sheet(
store: self.store.scope(
state: \.$staffDetail,
action: { .staffDetail($0) }
)
) { store in
StaffDetailView(store: store)
.presentationDetents([.medium])
}
}

@ViewBuilder
Expand Down
73 changes: 73 additions & 0 deletions KuringApp/KuringApp/Search/StaffDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// StaffDetail.swift
// KuringApp
//
// Created by 이재성 on 11/25/23.
//

import Model
import SwiftUI
import ComposableArchitecture

struct StaffDetailFeature: Reducer {
struct State: Equatable {
let staff: Staff
}

enum Action {
x-0o0 marked this conversation as resolved.
Show resolved Hide resolved
case emailAddressTapped
case phoneNumberTapped
}

var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .emailAddressTapped:
return .none

case .phoneNumberTapped:
return .none
}
}
}
}

struct StaffDetailView: View {
let store: StoreOf<StaffDetailFeature>

var body: some View {
WithViewStore(self.store, observe: { $0.staff }) { viewStore in
List {
Text(viewStore.name)
.font(.system(size: 20, weight: .bold))
.listRowSeparator(.hidden)

Text("\(viewStore.deptName) · \(viewStore.collegeName)")
.foregroundStyle(.secondary)
.listRowSeparator(.hidden)

Label(viewStore.email, systemImage: "envelope")
.listRowSeparator(.hidden)

Label(viewStore.lab, systemImage: "mappin.and.ellipse")
.listRowSeparator(.hidden)

Label(viewStore.phone, systemImage: "phone")
.listRowSeparator(.hidden)

Label(viewStore.major, systemImage: "book")
.listRowSeparator(.hidden)
}
.listStyle(.plain)
}
}
}

#Preview {
StaffDetailView(
store: Store(
initialState: StaffDetailFeature.State(staff: .random()),
reducer: { StaffDetailFeature() }
)
)
}