Skip to content

Commit

Permalink
[추가] NoticeList구현
Browse files Browse the repository at this point in the history
  • Loading branch information
lgvv authored and x-0o0 committed Nov 24, 2023
1 parent 0ac9b8b commit 29c43d1
Show file tree
Hide file tree
Showing 21 changed files with 962 additions and 155 deletions.
22 changes: 22 additions & 0 deletions KuringApp/KuringApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
DF331DAE2AC917E100D0BB08 /* kuring_app_blueprint.png in Resources */ = {isa = PBXBuildFile; fileRef = DF331DAA2AC917E000D0BB08 /* kuring_app_blueprint.png */; };
DFE7AB152AC332DB00230934 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFE7AB142AC332DB00230934 /* SettingView.swift */; };
DFE7AB172AC33D6700230934 /* AppIconSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFE7AB162AC33D6700230934 /* AppIconSelector.swift */; };
B1CBFA662AC7113C00C1E0ED /* NoticeRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CBFA652AC7113C00C1E0ED /* NoticeRow.swift */; };
CAD5A4272B10723500DED0D5 /* NoticeTypeGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A4262B10723500DED0D5 /* NoticeTypeGrid.swift */; };
CAD5A4292B10724100DED0D5 /* NoticeTypeColumn.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A4282B10724100DED0D5 /* NoticeTypeColumn.swift */; };
CAD5A42B2B10750800DED0D5 /* DepartmentSelectorLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A42A2B10750800DED0D5 /* DepartmentSelectorLink.swift */; };
CAD5A42D2B1077C200DED0D5 /* NoticeList.NoDepartment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD5A42C2B1077C200DED0D5 /* NoticeList.NoDepartment.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -85,6 +90,12 @@
DF331DAA2AC917E000D0BB08 /* kuring_app_blueprint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = kuring_app_blueprint.png; sourceTree = "<group>"; };
DFE7AB142AC332DB00230934 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = "<group>"; };
DFE7AB162AC33D6700230934 /* AppIconSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconSelector.swift; sourceTree = "<group>"; };
B1129A702AF7D11400FB2ED2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
B1CBFA652AC7113C00C1E0ED /* NoticeRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRow.swift; sourceTree = "<group>"; };
CAD5A4262B10723500DED0D5 /* NoticeTypeGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeTypeGrid.swift; sourceTree = "<group>"; };
CAD5A4282B10724100DED0D5 /* NoticeTypeColumn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeTypeColumn.swift; sourceTree = "<group>"; };
CAD5A42A2B10750800DED0D5 /* DepartmentSelectorLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DepartmentSelectorLink.swift; sourceTree = "<group>"; };
CAD5A42C2B1077C200DED0D5 /* NoticeList.NoDepartment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeList.NoDepartment.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -173,6 +184,11 @@
children = (
A9B4F0172ABCA9AF00354C00 /* NoticeDetailView.swift */,
A9B4F0192ABCAF9800354C00 /* NoticeList.swift */,
CAD5A42C2B1077C200DED0D5 /* NoticeList.NoDepartment.swift */,
B1CBFA652AC7113C00C1E0ED /* NoticeRow.swift */,
CAD5A4262B10723500DED0D5 /* NoticeTypeGrid.swift */,
CAD5A4282B10724100DED0D5 /* NoticeTypeColumn.swift */,
CAD5A42A2B10750800DED0D5 /* DepartmentSelectorLink.swift */,
);
path = NoticeList;
sourceTree = "<group>";
Expand Down Expand Up @@ -379,11 +395,17 @@
A9DAFA562AB1F04B0064F748 /* ContentView.swift in Sources */,
CA640C1B2AD8064B002836E0 /* NoticeProvider.swift in Sources */,
A9B4F01D2ABCB4CE00354C00 /* SearchView.swift in Sources */,
CAD5A42D2B1077C200DED0D5 /* NoticeList.NoDepartment.swift in Sources */,
CAD5A4272B10723500DED0D5 /* NoticeTypeGrid.swift in Sources */,
A965B7A32AC013060026ECDC /* DepartmentEditor.swift in Sources */,
A965B7A52AC013BF0026ECDC /* DepartmentSelector.swift in Sources */,
B11DBDCC2ACB370500501CA8 /* StaffRow.swift in Sources */,
A9B4F0162ABCA93400354C00 /* NoticeApp.Path.swift in Sources */,
A965B7A72AC0696B0026ECDC /* Department.swift in Sources */,
CAD5A42B2B10750800DED0D5 /* DepartmentSelectorLink.swift in Sources */,
A9B4F0182ABCA9AF00354C00 /* NoticeDetailView.swift in Sources */,
CAD5A4292B10724100DED0D5 /* NoticeTypeColumn.swift in Sources */,
B1CBFA662AC7113C00C1E0ED /* NoticeRow.swift in Sources */,
A965B7AF2AC084D20026ECDC /* SubscriptionApp.swift in Sources */,
A91455032ACF44CE00B82A8E /* KuringIcon.swift in Sources */,
CA640C192AD7FEFD002836E0 /* SubscriptionSegment.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion KuringApp/KuringApp/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct ContentView: View {
NoticeAppView(
store: Store(
initialState: NoticeAppFeature.State(
noticeList: NoticeListFeature.State(notices: [.random])
noticeList: NoticeListFeature.State()
),
reducer: { NoticeAppFeature() }
)
Expand Down
123 changes: 86 additions & 37 deletions KuringApp/KuringApp/Department/DepartmentEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct DepartmentEditorFeature: Reducer {
case deleteMyDepartmentButtonTapped(id: NoticeProvider.ID)
/// 내 학과 전체삭제 버튼 눌렀을 때
case deleteAllMyDepartmentButtonTapped
/// 텍스트 필드의 xmark를 눌렀을 때
case clearTextFieldButtonTapped

/// 알림
enum Alert: Equatable {
Expand Down Expand Up @@ -99,6 +101,9 @@ struct DepartmentEditorFeature: Reducer {
}
}
return .none
case .clearTextFieldButtonTapped:
state.searchText = ""
return .none

// MARK: Alert
case let .alert(.presented(alertAction)):
Expand Down Expand Up @@ -127,90 +132,133 @@ struct DepartmentEditor: View {
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
List {
Text("학과를 추가하거나 삭제할 수 있어요")

/**
- `viewStore.$searchText`
- `bind(viewStore.$focus, to: $focus)`
*/
Section {
TextField("추가할 학과를 검색해 주세요", text: viewStore.$searchText)
.focused($focus, equals: .search)
.bind(viewStore.$focus, to: self.$focus)
HStack {
Text("학과를 추가하거나 \n삭제할 수 있어요")
.font(.system(size: 24, weight: .bold))
.foregroundColor(Color(red: 0.1, green: 0.12, blue: 0.15))
Spacer()
}
.padding(.top, 28)
.padding(.bottom, 24)

HStack(alignment: .center, spacing: 12) {
if viewStore.searchText.isEmpty {
Image(systemName: "magnifyingglass")
.frame(width: 16, height: 16)
.foregroundStyle(Color(red: 0.21, green: 0.24, blue: 0.29).opacity(0.6))
}

/**
- `viewStore.myDepartments`
- `.deleteMyDepartmentButtonTapped`
*/
Section {
TextField("추가할 학과를 검색해 주세요", text: viewStore.$searchText)
.focused($focus, equals: .search)
.bind(viewStore.$focus, to: self.$focus)

if !viewStore.searchText.isEmpty {
Image(systemName: "xmark")
.frame(width: 16, height: 16)
.foregroundStyle(Color(red: 0.21, green: 0.24, blue: 0.29).opacity(0.6))
.onTapGesture {
viewStore.send(.clearTextFieldButtonTapped)
focus = nil
}
}
}
.padding(.horizontal, 16)
.padding(.vertical, 7)
.background(Color(red: 0.95, green: 0.95, blue: 0.96))
.cornerRadius(20)
.padding(.bottom, 16)

HStack(alignment: .center, spacing: 10) {
Text(viewStore.searchText.isEmpty ? "내 학과" : "검색 결과")
.font(.system(size: 14))
.foregroundStyle(Color(red: 0.21, green: 0.24, blue: 0.29).opacity(0.6))
Spacer()
}
.padding(.horizontal, 4)
.padding(.vertical, 10)

if viewStore.searchText.isEmpty {
// 내학과
ScrollView {
ForEach(viewStore.myDepartments) { myDepartment in
HStack {
HStack(alignment: .center) {
Text(myDepartment.korName)

Spacer()

Button("삭제") {
Button {
viewStore.send(.deleteMyDepartmentButtonTapped(id: myDepartment.id))
} label: {
Text("삭제")
.foregroundStyle(Color(red: 0.21, green: 0.24, blue: 0.29).opacity(0.6))
}
}
.padding(.horizontal, 4)
.padding(.vertical, 10)
}
} header: {
Text("내 학과")
}

/**
- `viewStore.results`
- `addDepartmentButtonTapped`
- `cancelAdditionButtonTapped`
*/
Section {
} else {
// 검색결과
ScrollView {
ForEach(viewStore.results) { result in
HStack {
HStack(alignment: .center) {
Text(result.korName)

Spacer()

Button {
if viewStore.myDepartments.contains(result) {
viewStore.send(.cancelAdditionButtonTapped(id: result.id))
} else {
viewStore.send(.addDepartmentButtonTapped(id: result.id))
}
} label: {
let isSelected = viewStore.myDepartments.contains(result)
Image(
systemName: viewStore.myDepartments.contains(result)
systemName: isSelected
? "checkmark.circle.fill"
: "plus.circle"
)
.foregroundStyle(
isSelected
? Color(red: 0.24, green: 0.74, blue: 0.5)
: Color.black.opacity(0.1)
)
}
}
.padding(.horizontal, 4)
.padding(.vertical, 10)
}
} header: {
Text("검색 결과")
}
}

Spacer()
}
.padding(.horizontal, 20)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("전체 삭제") {
Button {
viewStore.send(.deleteAllMyDepartmentButtonTapped)
focus = .search
} label: {
Text("전체 삭제")
.foregroundStyle(
viewStore.myDepartments.isEmpty
? Color(red: 0.21, green: 0.21, blue: 0.21).opacity(0.5)
: Color(red: 0.24, green: 0.74, blue: 0.5)
)
}
.disabled(viewStore.myDepartments.isEmpty)
}
}
.bind(viewStore.$focus, to: self.$focus)
.alert(
store: self.store.scope(
state: \.$alert,
action: { .alert($0) }
)
)
}

}
}


#Preview {
NavigationStack {
DepartmentEditor(
Expand All @@ -230,5 +278,6 @@ struct DepartmentEditor: View {
)
)
.navigationTitle("Department Editor")
// .toolbarTitleDisplayMode(.inline)
}
}
76 changes: 62 additions & 14 deletions KuringApp/KuringApp/Department/DepartmentSelector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct DepartmentSelectorFeature: Reducer {
var addedDepartment: IdentifiedArrayOf<NoticeProvider>
}

enum Action {
enum Action: Equatable {
// TODO: String -> Department
case selectDepartment(id: NoticeProvider.ID)
case editDepartmentsButtonTapped
Expand All @@ -36,7 +36,7 @@ struct DepartmentSelectorFeature: Reducer {
}
state.currentDepartment = department
return .none

case .editDepartmentsButtonTapped:
return .send(.delegate(.editDepartment))

Expand All @@ -52,28 +52,77 @@ struct DepartmentSelector: View {

var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
List {
Section {
VStack {
HStack(alignment: .center, spacing: 10) {
Text("대표 학과 선택")
.font(.system(size: 18, weight: .bold))
.foregroundStyle(Color.black)
}
.padding(.horizontal, 20)
.padding(.top, 24)
.padding(.bottom, 12)
.frame(width: 375, alignment: .leading)

ScrollView {
ForEach(viewStore.addedDepartment) { department in
Button {
viewStore.send(.selectDepartment(id: department.id))
} label: {
Label(
department.korName,
systemImage: department == viewStore.currentDepartment
HStack {
Text(department.id)
.font(.system(size: 16, weight: .medium))
.foregroundColor(.black)

Spacer()

Image(
systemName: department == viewStore.currentDepartment
? "checkmark.circle.fill"
: "circle"
)
.foregroundStyle(
department == viewStore.currentDepartment
? Color(red: 0.24, green: 0.74, blue: 0.5)
: Color.black.opacity(0.1)
)
.frame(width: 20, height: 20)
}
.padding(.horizontal, 20)
.padding(.vertical, 12)
.background(.white)
.onTapGesture {
viewStore.send(.selectDepartment(id: department.id))
}
}
}

Button("내 학과 편집하기") {
viewStore.send(.editDepartmentsButtonTapped)
}
topBlurButton(
"내 학과 편집하기",
fontColor:Color(red: 0.24, green: 0.74, blue: 0.5),
backgroundColor: Color(red: 0.24, green: 0.74, blue: 0.5).opacity(0.15)
)
.padding(.horizontal, 20)
}
}
}

// TODO: 디자인 시스템 분리 - 상단에 블러가 존재하는 버튼
@ViewBuilder
private func topBlurButton(_ title: String, fontColor: Color, backgroundColor: Color) -> some View {
HStack(alignment: .center, spacing: 10) {
Spacer()
Text(title)
.font(.system(size: 16, weight: .semibold))
.foregroundStyle(fontColor)
Spacer()
}
.padding(.horizontal, 50)
.padding(.vertical, 16)
.frame(height: 50, alignment: .center)
.background(backgroundColor)
.cornerRadius(100)
.background {
LinearGradient(gradient: Gradient(colors: [.white.opacity(0.1), .white]), startPoint: .top, endPoint: .bottom)
.offset(x: 0, y: -32)
}
}
}

#Preview {
Expand All @@ -90,6 +139,5 @@ struct DepartmentSelector: View {
reducer: { DepartmentSelectorFeature() }
)
)
.navigationTitle("Department Selector")
}
}
Loading

0 comments on commit 29c43d1

Please sign in to comment.