diff --git a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj index d4a8b18..ab1ebab 100644 --- a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj +++ b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ D473920C2C193C090059AE45 /* SheetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D473920B2C193C090059AE45 /* SheetType.swift */; }; D47392102C196C070059AE45 /* DateTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D473920F2C196C070059AE45 /* DateTimePicker.swift */; }; D47392122C198E250059AE45 /* DateFormatter + .swift in Sources */ = {isa = PBXBuildFile; fileRef = D47392112C198E250059AE45 /* DateFormatter + .swift */; }; + D476AF8F2C23FD0300943FA7 /* UIColor + hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D476AF8E2C23FD0200943FA7 /* UIColor + hex.swift */; }; D47A3AAB2C0CAC400031DCAA /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A3AAA2C0CAC400031DCAA /* SearchView.swift */; }; D47A3AAD2C0CAC4B0031DCAA /* SearchReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A3AAC2C0CAC4B0031DCAA /* SearchReducer.swift */; }; D47A3AB02C0CAD810031DCAA /* GymSearchResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47A3AAF2C0CAD810031DCAA /* GymSearchResult.swift */; }; @@ -97,6 +98,7 @@ D473920B2C193C090059AE45 /* SheetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetType.swift; sourceTree = ""; }; D473920F2C196C070059AE45 /* DateTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimePicker.swift; sourceTree = ""; }; D47392112C198E250059AE45 /* DateFormatter + .swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter + .swift"; sourceTree = ""; }; + D476AF8E2C23FD0200943FA7 /* UIColor + hex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor + hex.swift"; sourceTree = ""; }; D47A3AAA2C0CAC400031DCAA /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; D47A3AAC2C0CAC4B0031DCAA /* SearchReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchReducer.swift; sourceTree = ""; }; D47A3AAF2C0CAD810031DCAA /* GymSearchResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GymSearchResult.swift; sourceTree = ""; }; @@ -404,6 +406,7 @@ D47392092C192D7F0059AE45 /* View + onReadSize.swift */, D47392112C198E250059AE45 /* DateFormatter + .swift */, D42357532C1FC8910070DB70 /* Date + datesOfMonth.swift */, + D476AF8E2C23FD0200943FA7 /* UIColor + hex.swift */, ); path = Extension; sourceTree = ""; @@ -583,6 +586,7 @@ 04CFB9EC2C007F3100580395 /* Token.swift in Sources */, D44FF1F72C145E66005E9EB1 /* ActivityRecordReducer.swift in Sources */, D442A3DE2BF9D36500A58F92 /* SearchAPI.swift in Sources */, + D476AF8F2C23FD0300943FA7 /* UIColor + hex.swift in Sources */, D4B75EF02C0B3D540074870D /* Error + toAppError.swift in Sources */, D4F161782C1AAB6300BF4392 /* RootSelectionView.swift in Sources */, D47A3AB32C0CAE2D0031DCAA /* SearchUsecase.swift in Sources */, diff --git a/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Contents.json b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Contents.json new file mode 100644 index 0000000..ce358c1 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Vector@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Vector@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Vector@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@1x.png b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@1x.png new file mode 100644 index 0000000..89dd9ac Binary files /dev/null and b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@1x.png differ diff --git a/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@2x.png b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@2x.png new file mode 100644 index 0000000..5dc1bcb Binary files /dev/null and b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@2x.png differ diff --git a/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@3x.png b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@3x.png new file mode 100644 index 0000000..52a2f4b Binary files /dev/null and b/Climeet-iOS/Climeet-iOS/Assets.xcassets/Icons/ActivityRecord/activity_plus.imageset/Vector@3x.png differ diff --git a/Climeet-iOS/Climeet-iOS/Assets.xcassets/TextColor/text_06_5.colorset/Contents.json b/Climeet-iOS/Climeet-iOS/Assets.xcassets/TextColor/text_06_5.colorset/Contents.json new file mode 100644 index 0000000..ff1bea2 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Assets.xcassets/TextColor/text_06_5.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x64", + "green" : "0x64", + "red" : "0x64" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x64", + "green" : "0x64", + "red" : "0x64" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Climeet-iOS/Climeet-iOS/Common/Extension/UIColor + hex.swift b/Climeet-iOS/Climeet-iOS/Common/Extension/UIColor + hex.swift new file mode 100644 index 0000000..ac20168 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Common/Extension/UIColor + hex.swift @@ -0,0 +1,34 @@ +// +// UIColor + hex.swift +// Climeet-iOS +// +// Created by KOVI on 6/20/24. +// + +import SwiftUI + +extension UIColor { + convenience init?(hex: String) { + let r, g, b, a: CGFloat + if hex.hasPrefix("#") { + let start = hex.index(hex.startIndex, offsetBy: 1) + let hexColor = String(hex[start...]) + + if hexColor.count == 6 { + let scanner = Scanner(string: hexColor) + var hexNumber: UInt64 = 0 + + if scanner.scanHexInt64(&hexNumber) { + r = CGFloat((hexNumber & 0xff0000) >> 16) / 255 + g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255 + b = CGFloat(hexNumber & 0x0000ff) / 255 + a = 1.0 + + self.init(red: r, green: g, blue: b, alpha: a) + return + } + } + } + return nil + } +} diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarReducer.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarReducer.swift index e8c06d4..951b954 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarReducer.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarReducer.swift @@ -12,7 +12,8 @@ import ComposableArchitecture struct ActivityCalendarReducer { @Reducer enum Destination { - case selectDate(DateTimePickerReducer) + case selectDateHalfSheet(DateTimePickerReducer) + case recordActivitySheet(ActivityRecordReducer) } @ObservableState @@ -33,6 +34,7 @@ struct ActivityCalendarReducer { case recordButtonTapped case statisticButtonTapped case calendarTitleButtonTapped + case plusButtonTapped case destination(PresentationAction) } @@ -72,7 +74,7 @@ struct ActivityCalendarReducer { } reducer.selectedDate = datePickerSelectedDate ?? Date() - state.destination = .selectDate(reducer) + state.destination = .selectDateHalfSheet(reducer) return .none @@ -86,7 +88,14 @@ struct ActivityCalendarReducer { return .none - case let .destination(.presented(.selectDate(.delegate(.selectDate(selectedDate))))): + case .plusButtonTapped: + let reducer = ActivityRecordReducer.State() + + state.destination = .recordActivitySheet(reducer) + + return .none + + case let .destination(.presented(.selectDateHalfSheet(.delegate(.selectDate(selectedDate))))): let monthDifference = monthsBetweenNowDate(date: selectedDate) state.selectedMonth = monthDifference state.tappedCalendarDate = CalendarDate( diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarView.swift index d113f93..a4a59d8 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarView.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityCalendar/ActivityCalendarView.swift @@ -49,6 +49,20 @@ struct ActivityCalendarView: View { store.send(.calendarTitleButtonTapped) } ) + + HStack { + Spacer() + Button(action: { + store.send(.plusButtonTapped) + }, label: { + Image("activity_plus") + }) + .frame(width: 54, height: 54) + .background(Color.climeetMain) + .clipShape(Circle()) + } + .padding(.vertical, 37) + .padding(.trailing, 25) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(.text09) @@ -57,12 +71,19 @@ struct ActivityCalendarView: View { }) .sheet( item: $store.scope( - state: \.destination?.selectDate, - action: \.destination.selectDate) + state: \.destination?.selectDateHalfSheet, + action: \.destination.selectDateHalfSheet) ) { dateTimePickerStore in DateTimePickerView(store: dateTimePickerStore) .presentationDetents([.height(store.bottomSheetHeight)]) } + .fullScreenCover( + item: $store.scope( + state: \.destination?.recordActivitySheet, + action: \.destination.recordActivitySheet) + ) { recordActivityStore in + ActivityRecordView(store: recordActivityStore) + } } } diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift index 2c98441..414fba5 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift @@ -31,12 +31,14 @@ struct ActivityRecordReducer { case readViewSize(CGSize) case selectDateButtonTapped case selectTimeButtonTapped + case closeButtonTapped case destination(PresentationAction) case path(StackAction) } // MARK: Internal + @Dependency(\.dismiss) var dismiss var body: some ReducerOf { Reduce { state, action in switch action { @@ -75,6 +77,10 @@ struct ActivityRecordReducer { state.destination = .selectDateTime(reducer) return .none + + case .closeButtonTapped: + + return .run { _ in await dismiss() } case let .path(.element(_, action: .delegate(.selectGym(selectedGym)))): state.selectedGym = selectedGym diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift index f6f05b4..c56ca9e 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift @@ -73,9 +73,8 @@ struct ActivityRecordView: View { .background(.text08) .cornerRadius(5) } else { - // TODO: 캘린더 - Text("안녕하세요") - .foregroundColor(.red) + // TODO: 루트셀렉션 이니셜라이저 값 채워줘야함 + RootSelectionView() } } .padding(.leading, 28) @@ -87,8 +86,13 @@ struct ActivityRecordView: View { .background(.text09) .toolbar { ToolbarItem(placement: .topBarLeading) { - Image("activity_close") - .frame(width: 24, height: 24) + Button(action: { + store.send(.closeButtonTapped) + }, label: { + Image("activity_close") + .frame(width: 24, height: 24) + }) + } } .toolbarBackground( diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift index 1055dcd..04c5247 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift @@ -6,13 +6,37 @@ // import SwiftUI +import Kingfisher + +// MARK: ForTest +struct Difficulty: Identifiable { + var id = UUID() + let climeetDifficultyName: String + let gymDifficultyName: String + let difficulty: Int + let gymDifficultyColor: UIColor +} + +let testItems = ["Jaws", "Cheesegrater", "The Wallus", "Moonraker", "Starcatcher", "Dreamweaver"] +let testDifficultyList: [Difficulty] = [ + Difficulty(climeetDifficultyName: "VB", gymDifficultyName: "하양", difficulty: 0, gymDifficultyColor: UIColor.white), + Difficulty(climeetDifficultyName: "V1", gymDifficultyName: "빨강", difficulty: 1, gymDifficultyColor: UIColor(hex: "#F34040")!), + Difficulty(climeetDifficultyName: "서울", gymDifficultyName: "주황", difficulty: 2, gymDifficultyColor: UIColor(hex: "#FF9000")!), + Difficulty(climeetDifficultyName: "V3", gymDifficultyName: "노랑", difficulty: 3, gymDifficultyColor: UIColor(hex: "#FDDA16")!), + Difficulty(climeetDifficultyName: "V4", gymDifficultyName: "초록", difficulty: 4, gymDifficultyColor: UIColor(hex: "#63B75D")!), + Difficulty(climeetDifficultyName: "V5", gymDifficultyName: "하늘", difficulty: 5, gymDifficultyColor: UIColor(hex: "#74D5FF")!), + Difficulty(climeetDifficultyName: "V6", gymDifficultyName: "파랑", difficulty: 6, gymDifficultyColor: UIColor(hex: "#0094FF")!), + Difficulty(climeetDifficultyName: "V7", gymDifficultyName: "남색", difficulty: 7, gymDifficultyColor: UIColor(hex: "#393FD6")!), + Difficulty(climeetDifficultyName: "V8", gymDifficultyName: "갈색", difficulty: 8, gymDifficultyColor: UIColor(hex: "#6E4C41")!), + Difficulty(climeetDifficultyName: "V9+", gymDifficultyName: "회색", difficulty: 9, gymDifficultyColor: UIColor(hex: "#8B8B8B")!), + Difficulty(climeetDifficultyName: "C", gymDifficultyName: "컴피", difficulty: 10, gymDifficultyColor: UIColor(hex: "#000000")!) +] struct RootSelectionView: View { - let items = ["안녕하십니까", "여기는 파크123", "여", "여긴여", "여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는"] var body: some View { VStack { - Image(systemName: "cloud.fill") + KFImage(URL(string: "https://climeet-production-bucket.s3.ap-northeast-2.amazonaws.com/final_1.png")) .resizable() .aspectRatio(contentMode: .fill) .frame(height: 132) @@ -21,26 +45,44 @@ struct RootSelectionView: View { ScrollView(.horizontal) { HStack(spacing: 9) { - ForEach(items, id: \.self) { item in - VStack { + ForEach(testItems, id: \.self) { item in Button(action: { - + // TODO: Item ButtonAction }, label: { Text(item) + .font(.climeetFontParagraph5()) }) .padding(.horizontal, 16) .padding(.top, 5.5) .padding(.bottom, 6.5) - .background(Color.red) - .frame(height: 30) + .background(.text06) + .cornerRadius(8) + .frame(maxWidth: .infinity) - .cornerRadius(/*@START_MENU_TOKEN@*/3.0/*@END_MENU_TOKEN@*/) - } + .foregroundColor(.levelColorWhite) } } - .padding() } - Spacer() + .scrollIndicators(.never) + + ScrollView(.horizontal) { + HStack(spacing: 9) { + ForEach(testDifficultyList) { testDifficulty in + Button(action: { + // TODO: Difficulty ButtonAction + }, label: { + Text(testDifficulty.climeetDifficultyName) + .font(.climeetFontParagraph4()) + .foregroundColor(Color(testDifficulty.gymDifficultyColor)) + }) + .padding(.horizontal, 5) + .padding(.vertical, 8) + .background(.text065) + .clipShape(Circle()) + } + } + } + .scrollIndicators(.never) } } } @@ -48,13 +90,3 @@ struct RootSelectionView: View { #Preview { RootSelectionView() } - -/* - Text("Item \(item)") - .font(.headline) - .padding() - .background(Color.red) - .cornerRadius(10) - .foregroundColor(.white) - - */