diff --git a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj index 4a6b902..3a0de47 100644 --- a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj +++ b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj @@ -51,6 +51,10 @@ D4EE0CFD2BD14AFB004C6688 /* ResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE0CFC2BD14AFB004C6688 /* ResponseDTO.swift */; }; D4EE0CFF2BD14B59004C6688 /* ExampleAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE0CFE2BD14B59004C6688 /* ExampleAPI.swift */; }; D4EE0D032BD14BAB004C6688 /* Encodable + toDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE0D022BD14BAB004C6688 /* Encodable + toDictionary.swift */; }; + D4F161782C1AAB6300BF4392 /* RootSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F161772C1AAB6300BF4392 /* RootSelectionView.swift */; }; + D4F1617A2C1AFE1D00BF4392 /* ActivityRecordHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F161792C1AFE1C00BF4392 /* ActivityRecordHeader.swift */; }; + D4F1617C2C1B1F5000BF4392 /* ClimbingSetupButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F1617B2C1B1F5000BF4392 /* ClimbingSetupButton.swift */; }; + D4F1617E2C1B1F8B00BF4392 /* ClimbingSetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F1617D2C1B1F8B00BF4392 /* ClimbingSetupView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -97,6 +101,10 @@ D4EE0CFC2BD14AFB004C6688 /* ResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseDTO.swift; sourceTree = ""; }; D4EE0CFE2BD14B59004C6688 /* ExampleAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleAPI.swift; sourceTree = ""; }; D4EE0D022BD14BAB004C6688 /* Encodable + toDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable + toDictionary.swift"; sourceTree = ""; }; + D4F161772C1AAB6300BF4392 /* RootSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootSelectionView.swift; sourceTree = ""; }; + D4F161792C1AFE1C00BF4392 /* ActivityRecordHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityRecordHeader.swift; sourceTree = ""; }; + D4F1617B2C1B1F5000BF4392 /* ClimbingSetupButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClimbingSetupButton.swift; sourceTree = ""; }; + D4F1617D2C1B1F8B00BF4392 /* ClimbingSetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClimbingSetupView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -189,6 +197,8 @@ children = ( D44FF1F42C145872005E9EB1 /* ActivityRecordView.swift */, D44FF1F62C145E66005E9EB1 /* ActivityRecordReducer.swift */, + D4F161742C1AAB4200BF4392 /* View */, + D4F161732C1AAB2300BF4392 /* Model */, ); path = ActivityRecord; sourceTree = ""; @@ -346,6 +356,24 @@ path = Repository; sourceTree = ""; }; + D4F161732C1AAB2300BF4392 /* Model */ = { + isa = PBXGroup; + children = ( + ); + path = Model; + sourceTree = ""; + }; + D4F161742C1AAB4200BF4392 /* View */ = { + isa = PBXGroup; + children = ( + D4F161772C1AAB6300BF4392 /* RootSelectionView.swift */, + D4F161792C1AFE1C00BF4392 /* ActivityRecordHeader.swift */, + D4F1617B2C1B1F5000BF4392 /* ClimbingSetupButton.swift */, + D4F1617D2C1B1F8B00BF4392 /* ClimbingSetupView.swift */, + ); + path = View; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -462,6 +490,7 @@ D473920C2C193C090059AE45 /* SheetType.swift in Sources */, D4EE0D032BD14BAB004C6688 /* Encodable + toDictionary.swift in Sources */, D4B75EEE2C0B3CAA0074870D /* AppError.swift in Sources */, + D4F1617A2C1AFE1D00BF4392 /* ActivityRecordHeader.swift in Sources */, 04CFB9EE2C007F4900580395 /* test.swift in Sources */, D47A3AB02C0CAD810031DCAA /* GymSearchResult.swift in Sources */, D47A3AB52C0CAF750031DCAA /* ResponseDTO + mapping.swift in Sources */, @@ -472,10 +501,12 @@ D4930E312C0F3EE2002E138B /* Text + init.swift in Sources */, D47A3AAD2C0CAC4B0031DCAA /* SearchReducer.swift in Sources */, D4EE0CF82BD149EF004C6688 /* Router.swift in Sources */, + D4F1617C2C1B1F5000BF4392 /* ClimbingSetupButton.swift in Sources */, D4E282052C0D4A7400567B92 /* UserRepository.swift in Sources */, D47A3AAB2C0CAC400031DCAA /* SearchView.swift in Sources */, D44FF1F52C145872005E9EB1 /* ActivityRecordView.swift in Sources */, D4EE0CFD2BD14AFB004C6688 /* ResponseDTO.swift in Sources */, + D4F1617E2C1B1F8B00BF4392 /* ClimbingSetupView.swift in Sources */, B94EC2262BD13CBB00DC3FDB /* Climeet_iOSApp.swift in Sources */, D44FF2282C183574005E9EB1 /* DateTimePickerReducer.swift in Sources */, D442A3E12BF9D3F400A58F92 /* SearchRequestModel.swift in Sources */, @@ -486,6 +517,7 @@ D44FF1F72C145E66005E9EB1 /* ActivityRecordReducer.swift in Sources */, D442A3DE2BF9D36500A58F92 /* SearchAPI.swift in Sources */, D4B75EF02C0B3D540074870D /* Error + toAppError.swift in Sources */, + D4F161782C1AAB6300BF4392 /* RootSelectionView.swift in Sources */, D47A3AB32C0CAE2D0031DCAA /* SearchUsecase.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Climeet-iOS/Climeet-iOS/.DS_Store b/Climeet-iOS/Climeet-iOS/.DS_Store index 5008ddf..e6dd848 100644 Binary files a/Climeet-iOS/Climeet-iOS/.DS_Store and b/Climeet-iOS/Climeet-iOS/.DS_Store differ diff --git a/Climeet-iOS/Climeet-iOS/Common/Extension/DateFormatter + .swift b/Climeet-iOS/Climeet-iOS/Common/Extension/DateFormatter + .swift index 1762ca6..498fb62 100644 --- a/Climeet-iOS/Climeet-iOS/Common/Extension/DateFormatter + .swift +++ b/Climeet-iOS/Climeet-iOS/Common/Extension/DateFormatter + .swift @@ -20,19 +20,19 @@ extension DateFormatter { // MARK: 2023년 12월 12일 (화) static let koreanFullDateWithDayFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy년 MM월 dd일 (E)" - formatter.timeZone = TimeZone(identifier: "Asia/Seoul") - formatter.locale = Locale(identifier: "ko_KR") - return formatter + let formatter = DateFormatter() + formatter.dateFormat = "yyyy년 MM월 dd일 (E)" + formatter.timeZone = TimeZone(identifier: "Asia/Seoul") + formatter.locale = Locale(identifier: "ko_KR") + return formatter }() // MARK: AM 9:00 static let amTimeFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "a h:mm" - formatter.timeZone = TimeZone(identifier: "Asia/Seoul") - formatter.locale = Locale(identifier: "en_US_POSIX") // AM/PM 표기를 위해 영어 로케일 사용 - return formatter - }() + let formatter = DateFormatter() + formatter.dateFormat = "a h:mm" + formatter.timeZone = TimeZone(identifier: "Asia/Seoul") + formatter.locale = Locale(identifier: "en_US_POSIX") // AM/PM 표기를 위해 영어 로케일 사용 + return formatter + }() } diff --git a/Climeet-iOS/Climeet-iOS/Domain/GymSearchResult.swift b/Climeet-iOS/Climeet-iOS/Domain/GymSearchResult.swift index 418e3dd..521711a 100644 --- a/Climeet-iOS/Climeet-iOS/Domain/GymSearchResult.swift +++ b/Climeet-iOS/Climeet-iOS/Domain/GymSearchResult.swift @@ -22,4 +22,20 @@ struct Gym: Identifiable { let follower: Int let profileImageUrl: String let isFollow: Bool? + + init( + gymId: Int? = nil, + name: String = "", + managerId: Int? = nil, + follower: Int = 0, + profileImageUrl: String = "", + isFollow: Bool? = nil) + { + self.gymId = gymId + self.name = name + self.managerId = managerId + self.follower = follower + self.profileImageUrl = profileImageUrl + self.isFollow = isFollow + } } diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift index b6e1cc6..2c98441 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordReducer.swift @@ -20,7 +20,7 @@ struct ActivityRecordReducer { struct State { var screenSize = CGSize(width: 0, height: 0) var bottomSheetHeight: CGFloat = 0.0 - var selectedGymName = "" + var selectedGym = Gym() var selectedDate = "" var selectedTime = "" @Presents var destination: Destination.State? @@ -44,26 +44,40 @@ struct ActivityRecordReducer { state.screenSize = viewSize return .none + case .selectDateButtonTapped: state.bottomSheetHeight = state.screenSize.height * SheetType.datePicker.displaySizeRatio - state.destination = .selectDateTime( - DateTimePickerReducer.State( - sheetType: .datePicker - ) + + var reducer = DateTimePickerReducer.State( + sheetType: .datePicker ) + if !state.selectedDate.isEmpty { + reducer.selectedDate = parseKoreanFullToDate( + dateString: state.selectedDate + ) + } + state.destination = .selectDateTime(reducer) + return .none case .selectTimeButtonTapped: state.bottomSheetHeight = state.screenSize.height * SheetType.timePicker.displaySizeRatio - state.destination = .selectDateTime( - DateTimePickerReducer.State( - sheetType: .timePicker - ) + + var reducer = DateTimePickerReducer.State( + sheetType: .timePicker ) + + if !state.selectedTime.isEmpty { + let times = parseTimeRange(timeRange: state.selectedTime) + reducer.selectedStartTime = times.start + reducer.selectedEndTime = times.end + } + state.destination = .selectDateTime(reducer) + return .none case let .path(.element(_, action: .delegate(.selectGym(selectedGym)))): - state.selectedGymName = selectedGym.name + state.selectedGym = selectedGym return .none @@ -81,8 +95,8 @@ struct ActivityRecordReducer { // MARK: tacocat 사용 Delegate case let .destination(.presented(.searchGyms(.delegate(.selectGym(selectedGym))))): - state.selectedGymName = selectedGym.name - print(state.selectedGymName) + state.selectedGym = selectedGym + print(state.selectedGym) return .none @@ -98,3 +112,34 @@ struct ActivityRecordReducer { } } } + +extension ActivityRecordReducer { + + /// AM 9:00 ~ AM 11:00 -> `(Date, Date)` + private func parseTimeRange(timeRange: String) -> (start: Date, end: Date) { + let dateFormatter = DateFormatter.amTimeFormatter + + let times = timeRange + .split(separator: "~") + .map { $0.trimmingCharacters(in: .whitespaces) } + + guard times.count == 2, + let startTime = dateFormatter.date(from: String(times[0])), + let endTime = dateFormatter.date(from: String(times[1])) else { + return (Date(), Date()) + } + + return (startTime, endTime) + } + + /// 2023년 12월 12일 (화) -> `Date` + private func parseKoreanFullToDate(dateString: String) -> Date { + guard + let date = DateFormatter.koreanFullDateWithDayFormatter.date( + from: dateString) else { + return Date() + } + + return date + } +} diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift index de70528..bc3bde0 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/ActivityRecordView.swift @@ -13,131 +13,87 @@ struct ActivityRecordView: View { var body: some View { NavigationStack(path: $store.scope(state: \.path, action: \.path)) { - VStack { - HStack { - Image("activity_close") - .frame(width: 24, height: 24, alignment: .leading) // 이미지 프레임 설정 - .padding(.top, 52) // 상단에서 52만큼 떨어진 위치 - .padding(.leading, 16) - Spacer() - } - + ScrollView(.vertical) { VStack { - HStack { - Text("날짜") - .font(.climeetFontTitle4()) - .foregroundColor(.levelColorWhite) - Spacer() + VStack { + ActivityRecordHeader(text: "날짜") + .padding(.top, 28) + .padding(.bottom, 13) + + ClimbingSetupButton( + placeholderText: "날짜를 입력해주세요", + text: store.selectedDate, + isEmpty: store.selectedDate.isEmpty) { + store.send(.selectDateButtonTapped) + } + + ClimbingSetupButton( + placeholderText: "시간을 선택해주세요(선택)", + text: store.selectedTime, + isEmpty: store.selectedTime.isEmpty) { + store.send(.selectTimeButtonTapped) + } } - .padding(.top, 28) - .padding(.bottom, 13) + .padding(.leading, 28) + .padding(.trailing, 26) - Button(action: { - store.send(.selectDateButtonTapped) - }) { - Text( - store.selectedDate.isEmpty ? "날짜를 선택해주세요" - : store.selectedDate - ) - .font(.climeetFontParagraph2()) - .foregroundColor( - store.selectedDate.isEmpty ? Color(red: 198/255, green: 198/255, blue: 198/255) - : .levelColorWhite + VStack { + ActivityRecordHeader(text: "암장") + .padding(.top, 28) + .padding(.bottom, 13) + + NavigationLink(state: SearchReducer.State()) { + ClimbingSetupView( + placeholderText: "클라이밍 암장을 선택해주세요", + text: store.selectedGym.name, + isEmpty: store.selectedGym.name.isEmpty ) - .padding(.leading, 18) - Spacer() - Image(uiImage: UIImage(named: "activity_arrow_right")!) - .padding(.trailing, 20) + } + .frame(maxWidth: .infinity, minHeight: 48) + .background(Color(red: 61/255, green: 61/255, blue: 61/255)) + .cornerRadius(5) } - .frame(maxWidth: .infinity, minHeight: 48) - .background(Color(red: 61/255, green: 61/255, blue: 61/255)) - .cornerRadius(5) + .padding(.leading, 28) + .padding(.trailing, 26) - Button(action: { - store.send(.selectTimeButtonTapped) - }) { - Text( - store.selectedTime.isEmpty ? "시간을 선택해주세요(선택)" - : store.selectedTime - ) - .font(.climeetFontParagraph2()) - .foregroundColor( - store.selectedTime.isEmpty ? Color(red: 198/255, green: 198/255, blue: 198/255) - : .levelColorWhite - ) - .padding(.leading, 18) - Spacer() - Image(uiImage: UIImage(named: "activity_arrow_right")!) - .padding(.trailing, 20) - } - .frame(maxWidth: .infinity, minHeight: 48) - .background(Color(red: 61/255, green: 61/255, blue: 61/255)) - .cornerRadius(5) - } - .padding(.leading, 28) - .padding(.trailing, 26) - - VStack { - HStack { - Text("암장") - .font(.climeetFontTitle4()) - .foregroundColor(.levelColorWhite) - Spacer() - } - .padding(.top, 28) - .padding(.bottom, 13) - - NavigationLink(state: SearchReducer.State()) { - Text( - store.selectedGymName.isEmpty ? "클라이밍 암장을 선택해주세요" - : store.selectedGymName - ) - .font(.climeetFontParagraph2()) - .foregroundColor( - store.selectedGymName.isEmpty ? Color(red: 198/255, green: 198/255, blue: 198/255) - : .levelColorWhite - ) - .padding(.leading, 18) - Spacer() - Image(uiImage: UIImage(named: "activity_arrow_right")!) - .padding(.trailing, 20) - } - .frame(maxWidth: .infinity, minHeight: 48) - .background(Color(red: 61/255, green: 61/255, blue: 61/255)) - .cornerRadius(5) - } - .padding(.leading, 28) - .padding(.trailing, 26) - - VStack { - HStack { - Text("루트기록") - .font(.climeetFontTitle4()) - .foregroundColor(.levelColorWhite) - Spacer() + VStack { + ActivityRecordHeader(text: "루트기록") + .padding(.top, 28) + .padding(.bottom, 13) + + if store.selectedGym.name.isEmpty { + NavigationLink(state: SearchReducer.State()) { + ClimbingSetupView( + placeholderText: "암장을 선택하면 루트를 기록할 수 있어요!", + text: "", + isEmpty: store.selectedGym.name.isEmpty + ) + } + .frame(maxWidth: .infinity, minHeight: 48) + .background(Color(red: 61/255, green: 61/255, blue: 61/255)) + .cornerRadius(5) + } else { + Text("안녕하세요") + .foregroundColor(.red) + } } - .padding(.top, 28) - .padding(.bottom, 13) - - NavigationLink(state: SearchReducer.State()) { - Text("암장을 선택하면 루트를 기록할 수 있어요!") - .font(.climeetFontParagraph2()) - .foregroundColor(Color(red: 198/255, green: 198/255, blue: 198/255)) - .padding(.leading, 18) - Spacer() - Image(uiImage: UIImage(named: "activity_arrow_right")!) - .padding(.trailing, 20) - } - .frame(maxWidth: .infinity, minHeight: 48) - .background(Color(red: 61/255, green: 61/255, blue: 61/255)) - .cornerRadius(5) + .padding(.leading, 28) + .padding(.trailing, 26) + Spacer() } - .padding(.leading, 28) - .padding(.trailing, 26) - Spacer() + .frame(maxWidth: .infinity, maxHeight: .infinity) } - .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(red: 51/255, green: 51/255, blue: 51/255)) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Image("activity_close") + .frame(width: 24, height: 24) + } + } + .toolbarBackground( + Color(red: 51/255, green: 51/255, blue: 51/255), + for: .navigationBar + ) } destination: { store in SearchView(store: store) } @@ -148,9 +104,6 @@ struct ActivityRecordView: View { ) { searchStore in SearchView(store: searchStore) } - .onReadSize({ size in - store.send(.readViewSize(size)) - }) .sheet( item: $store.scope( state: \.destination?.selectDateTime, @@ -159,6 +112,9 @@ struct ActivityRecordView: View { DateTimePickerView(store: dateTimePickerStore) .presentationDetents([.height(store.bottomSheetHeight)]) } + .onReadSize({ size in + store.send(.readViewSize(size)) + }) } } diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ActivityRecordHeader.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ActivityRecordHeader.swift new file mode 100644 index 0000000..8f9919f --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ActivityRecordHeader.swift @@ -0,0 +1,21 @@ +// +// ActivityHeader.swift +// Climeet-iOS +// +// Created by KOVI on 6/13/24. +// + +import SwiftUI + +struct ActivityRecordHeader: View { + var text: String + + var body: some View { + HStack { + Text(text) + .font(.climeetFontTitle4()) + .foregroundColor(.levelColorWhite) + Spacer() + } + } +} diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupButton.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupButton.swift new file mode 100644 index 0000000..95006a7 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupButton.swift @@ -0,0 +1,37 @@ +// +// ClimbingSetupButton.swift +// Climeet-iOS +// +// Created by KOVI on 6/13/24. +// + +import SwiftUI + +struct ClimbingSetupButton: View { + var placeholderText: String + var text: String + var isEmpty: Bool + var action: () -> Void + + var body: some View { + Button(action: action, label: { + HStack { + Text(isEmpty ? placeholderText : text) + .font(.climeetFontParagraph2()) + .foregroundColor( + isEmpty ? Color(red: 198/255, green: 198/255, blue: 198/255) + : .levelColorWhite + ) + .padding(.leading, 18) + + Spacer() + + Image(uiImage: UIImage(named: "activity_arrow_right")!) + .padding(.trailing, 20) + } + }) + .frame(maxWidth: .infinity, minHeight: 48) + .background(Color(red: 61/255, green: 61/255, blue: 61/255)) + .cornerRadius(5) + } +} diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupView.swift new file mode 100644 index 0000000..80ffdd6 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/ClimbingSetupView.swift @@ -0,0 +1,29 @@ +// +// ClimbingSetupView.swift +// Climeet-iOS +// +// Created by KOVI on 6/13/24. +// + +import SwiftUI + +struct ClimbingSetupView: View { + var placeholderText: String + var text: String + var isEmpty: Bool + + var body: some View { + HStack { + Text(isEmpty ? placeholderText : text) + .font(.climeetFontParagraph2()) + .foregroundColor( + isEmpty ? Color(red: 198/255, green: 198/255, blue: 198/255) + : .levelColorWhite + ) + .padding(.leading, 18) + Spacer() + Image(uiImage: UIImage(named: "activity_arrow_right")!) + .padding(.trailing, 20) + } + } +} diff --git a/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift new file mode 100644 index 0000000..1055dcd --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Presentation/ActivityRecord/View/RootSelectionView.swift @@ -0,0 +1,60 @@ +// +// RootSelectionView.swift +// Climeet-iOS +// +// Created by KOVI on 6/13/24. +// + +import SwiftUI + +struct RootSelectionView: View { + let items = ["안녕하십니까", "여기는 파크123", "여", "여긴여", "여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는여긴여파크입니다여기는"] + + var body: some View { + VStack { + Image(systemName: "cloud.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(height: 132) + .frame(maxWidth: .infinity) + .cornerRadius(5) + + ScrollView(.horizontal) { + HStack(spacing: 9) { + ForEach(items, id: \.self) { item in + VStack { + Button(action: { + + }, label: { + Text(item) + }) + .padding(.horizontal, 16) + .padding(.top, 5.5) + .padding(.bottom, 6.5) + .background(Color.red) + .frame(height: 30) + .frame(maxWidth: .infinity) + .cornerRadius(/*@START_MENU_TOKEN@*/3.0/*@END_MENU_TOKEN@*/) + } + } + } + .padding() + } + Spacer() + } + } +} + +#Preview { + RootSelectionView() +} + +/* + Text("Item \(item)") + .font(.headline) + .padding() + .background(Color.red) + .cornerRadius(10) + .foregroundColor(.white) + + */ diff --git a/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerReducer.swift b/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerReducer.swift index cb8f310..6c4be89 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerReducer.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerReducer.swift @@ -13,11 +13,25 @@ struct DateTimePickerReducer { @ObservableState struct State { var sheetType: SheetType - var selectedDate = Date() + // ... For DatePicker + var selectedDate: Date var isSelectedDateToday = true + // ... For TimePicker var isStartPickerActive = true - var selectedStartTime = Date() - var selectedEndTime = Date().addingTimeInterval(7200) + var selectedStartTime: Date + var selectedEndTime: Date + + init( + sheetType: SheetType, + selectedDate: Date = Date(), + selectedStartTime: Date = Date(), + selectedEndTime: Date = Date().addingTimeInterval(7200)) + { + self.sheetType = sheetType + self.selectedDate = selectedDate + self.selectedStartTime = selectedStartTime + self.selectedEndTime = selectedEndTime + } } enum Action { diff --git a/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerView.swift b/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerView.swift index 049d6bd..4fa4fc2 100644 --- a/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerView.swift +++ b/Climeet-iOS/Climeet-iOS/Presentation/DateTimePicker/DateTimePickerView.swift @@ -110,7 +110,11 @@ struct DateTimePickerView: View { .font(.climeetFontTitle3()) .foregroundColor(.levelColorWhite) Spacer() - Image(uiImage: UIImage(named: "datepicker_close")!) + Button { + store.send(.cancelButtonTapped) + } label: { + Image(uiImage: UIImage(named: "datepicker_close")!) + } } .padding(.leading, 13.5) .padding(.trailing, 9.5)