diff --git a/SodaLive/Sources/Content/Create/ContentCreateView.swift b/SodaLive/Sources/Content/Create/ContentCreateView.swift index 037d869..3daea4d 100644 --- a/SodaLive/Sources/Content/Create/ContentCreateView.swift +++ b/SodaLive/Sources/Content/Create/ContentCreateView.swift @@ -16,6 +16,8 @@ struct ContentCreateView: View { @State private var isShowPhotoPicker = false @State private var isShowSelectAudioView = false @State private var isShowSelectThemeView = false + @State private var isShowSelectDateView = false + @State private var isShowSelectTimeView = false var body: some View { BaseView(isLoading: $viewModel.isLoading) { @@ -37,7 +39,7 @@ struct ContentCreateView: View { .resizable() .scaledToFill() .frame(width: 107, height: 107) - .background(Color(hex: "3e3358")) + .background(Color(hex: "13181b")) .cornerRadius(8) .clipped() } else { @@ -46,13 +48,13 @@ struct ContentCreateView: View { .scaledToFit() .padding(13.3) .frame(width: 107, height: 107) - .background(Color(hex: "3e3358")) + .background(Color(hex: "13181b")) .cornerRadius(8) } Image("ic_camera") .padding(10) - .background(Color(hex: "9970ff")) + .background(Color(hex: "3bb9f1")) .cornerRadius(30) .offset(x: 50, y: 36) } @@ -67,15 +69,15 @@ struct ContentCreateView: View { Text(viewModel.fileName.trimmingCharacters(in: .whitespacesAndNewlines) == "" ? "파일선택" : viewModel.fileName) .font(.custom(Font.medium.rawValue, size: 16.7)) - .foregroundColor(Color(hex: "9970ff")) + .foregroundColor(Color(hex: "3bb9f1")) .padding(.vertical, 10) .frame(maxWidth: .infinity) - .background(Color(hex: "9970ff").opacity(0.2)) + .background(Color(hex: "13181b")) .cornerRadius(5.3) .overlay( RoundedCorner(radius: 8) .stroke(lineWidth: 2) - .foregroundColor(Color(hex: "9970ff")) + .foregroundColor(Color(hex: "3bb9f1")) ) .padding(.top, 13.3) .onTapGesture { isShowSelectAudioView = true } @@ -150,16 +152,16 @@ struct ContentCreateView: View { viewModel.theme!.theme : "테마 선택") .font(.custom(Font.bold.rawValue, size: 16.7)) - .foregroundColor(Color(hex: "9970ff")) + .foregroundColor(Color(hex: "3bb9f1")) } .padding(.vertical, viewModel.theme != nil ? 8 : 13.3) .frame(maxWidth: .infinity) - .background(Color(hex: "9970ff").opacity(0.2)) + .background(Color(hex: "13181b")) .cornerRadius(24) .overlay( RoundedRectangle(cornerRadius: 24) .stroke(lineWidth: 2) - .foregroundColor(Color(hex: "9970ff")) + .foregroundColor(Color(hex: "3bb9f1")) ) .padding(.top, 13.3) .onTapGesture { @@ -287,6 +289,62 @@ struct ContentCreateView: View { } .padding(.top, 26.7) } + + if !viewModel.isFree { + VStack(spacing: 10) { + Text("미리듣기 시간 설정") + .font(.custom(Font.bold.rawValue, size: 16.7)) + .foregroundColor(Color(hex: "eeeeee")) + .frame(maxWidth: .infinity, alignment: .leading) + + Text("미리듣기 시간을 직접 설정하지 않으면 콘텐츠 앞부분 30초가 자동으로 설정됩니다. 미리듣기의 시간제한은 없습니다.") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "777777")) + .frame(maxWidth: .infinity, alignment: .leading) + + HStack(spacing: 13.3) { + VStack(spacing: 5.3) { + Text("시작 시간") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "d2d2d2")) + .frame(maxWidth: .infinity, alignment: .leading) + + TextField("00:00:00", text: $viewModel.previewStartTime) + .autocapitalization(.none) + .disableAutocorrection(true) + .font(.custom(Font.bold.rawValue, size: 14.6)) + .foregroundColor(Color(hex: "777777")) + .padding(.vertical, 16.7) + .padding(.horizontal, 13.3) + .background(Color(hex: "222222")) + .cornerRadius(6.7) + .keyboardType(.default) + .multilineTextAlignment(.center) + } + + VStack(spacing: 5.3) { + Text("종료 시간") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "d2d2d2")) + .frame(maxWidth: .infinity, alignment: .leading) + + TextField("00:00:30", text: $viewModel.previewEndTime) + .autocapitalization(.none) + .disableAutocorrection(true) + .font(.custom(Font.bold.rawValue, size: 14.6)) + .foregroundColor(Color(hex: "777777")) + .padding(.vertical, 16.7) + .padding(.horizontal, 13.3) + .background(Color(hex: "222222")) + .cornerRadius(6.7) + .keyboardType(.default) + .multilineTextAlignment(.center) + } + } + .padding(.top, 3.3) + } + .padding(.top, 26.7) + } } .padding(.top, 26.7) .padding(.horizontal, 13.3) @@ -343,62 +401,79 @@ struct ContentCreateView: View { .padding(.top, 26.7) .padding(.horizontal, 13.3) - if !viewModel.isFree { - VStack(spacing: 10) { - Text("미리듣기 시간 설정") - .font(.custom(Font.bold.rawValue, size: 16.7)) - .foregroundColor(Color(hex: "eeeeee")) - .frame(maxWidth: .infinity, alignment: .leading) - - Text("미리듣기 시간을 직접 설정하지 않으면 콘텐츠 앞부분 30초가 자동으로 설정됩니다. 미리듣기의 시간제한은 없습니다.") - .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "777777")) - .frame(maxWidth: .infinity, alignment: .leading) - - HStack(spacing: 13.3) { - VStack(spacing: 5.3) { - Text("시작 시간") - .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "d2d2d2")) - .frame(maxWidth: .infinity, alignment: .leading) - - TextField("00:00:00", text: $viewModel.previewStartTime) - .autocapitalization(.none) - .disableAutocorrection(true) - .font(.custom(Font.bold.rawValue, size: 14.6)) - .foregroundColor(Color(hex: "777777")) - .padding(.vertical, 16.7) - .padding(.horizontal, 13.3) - .background(Color(hex: "222222")) - .cornerRadius(6.7) - .keyboardType(.default) - .multilineTextAlignment(.center) - } - - VStack(spacing: 5.3) { - Text("종료 시간") - .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "d2d2d2")) - .frame(maxWidth: .infinity, alignment: .leading) - - TextField("00:00:30", text: $viewModel.previewEndTime) - .autocapitalization(.none) - .disableAutocorrection(true) - .font(.custom(Font.bold.rawValue, size: 14.6)) - .foregroundColor(Color(hex: "777777")) - .padding(.vertical, 16.7) - .padding(.horizontal, 13.3) - .background(Color(hex: "222222")) - .cornerRadius(6.7) - .keyboardType(.default) - .multilineTextAlignment(.center) + VStack(spacing: 13.3) { + Text("예약 공개") + .font(.custom(Font.bold.rawValue, size: 16.7)) + .foregroundColor(Color(hex: "eeeeee")) + .frame(maxWidth: .infinity, alignment: .leading) + + HStack(spacing: 13.3) { + SelectButtonView(title: "지금 공개", isChecked: !viewModel.isActiveReservation) { + if viewModel.isActiveReservation { + viewModel.isActiveReservation = false + } + } + + SelectButtonView(title: "예약 공개", isChecked: viewModel.isActiveReservation) { + if !viewModel.isActiveReservation { + viewModel.isActiveReservation = true } } - .padding(.top, 3.3) } - .padding(.top, 26.7) - .padding(.horizontal, 13.3) + + if viewModel.isActiveReservation { + HStack(spacing: 13.3) { + VStack(alignment: .leading, spacing: 6.7) { + Text("예약 날짜") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "eeeeee")) + + Button(action: { + hideKeyboard() + self.isShowSelectDateView = true + }) { + Text(viewModel.releaseDateString) + .font(.custom(Font.medium.rawValue, size: 14.7)) + .foregroundColor(Color(hex: "eeeeee")) + .frame(maxWidth: .infinity) + .frame(height: 48.7) + .overlay( + RoundedRectangle(cornerRadius: 6.7) + .stroke(Color(hex: "3bb9f1"), lineWidth: 1.3) + ) + } + } + + VStack(alignment: .leading, spacing: 6.7) { + Text("예약 시간") + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color(hex: "eeeeee")) + + Button(action: { + hideKeyboard() + self.isShowSelectTimeView = true + }) { + Text(viewModel.releaseTimeString) + .font(.custom(Font.medium.rawValue, size: 14.7)) + .foregroundColor(Color(hex: "eeeeee")) + .frame(maxWidth: .infinity) + .frame(height: 48.7) + .overlay( + RoundedRectangle(cornerRadius: 6.7) + .stroke(Color(hex: "3bb9f1"), lineWidth: 1.3) + ) + } + } + } + .padding(.horizontal, 13.3) + .padding(.vertical, 14.2) + .frame(maxWidth: .infinity) + .background(Color(hex: "222222")) + .padding(.top, 22.7) + } } + .padding(.top, 26.7) + .padding(.horizontal, 13.3) VStack(spacing: 0) { HStack(alignment: .top, spacing: 0) { @@ -407,7 +482,7 @@ struct ContentCreateView: View { .foregroundColor(Color.white) .frame(height: 50) .frame(maxWidth: .infinity) - .background(Color(hex: "9970ff")) + .background(Color(hex: "3bb9f1")) .cornerRadius(10) .padding(13.3) } @@ -449,6 +524,14 @@ struct ContentCreateView: View { } } + if isShowSelectDateView { + SelectDatePicker(selectedDate: $viewModel.releaseDate, isShowing: $isShowSelectDateView) + } + + if isShowSelectTimeView { + QuarterTimePickerView(selectedTime: $viewModel.releaseTime, isShowing: $isShowSelectTimeView) + } + if isShowPhotoPicker { ImagePicker( isShowing: $isShowPhotoPicker, @@ -494,7 +577,7 @@ struct ContentCreateView: View { .padding(.vertical, 13.3) .frame(width: screenSize().width - 66.7, alignment: .center) .font(.custom(Font.medium.rawValue, size: 12)) - .background(Color(hex: "9970ff")) + .background(Color(hex: "3bb9f1")) .foregroundColor(Color.white) .multilineTextAlignment(.center) .cornerRadius(20) diff --git a/SodaLive/Sources/Content/Create/ContentCreateViewModel.swift b/SodaLive/Sources/Content/Create/ContentCreateViewModel.swift index b6c831c..b010fc7 100644 --- a/SodaLive/Sources/Content/Create/ContentCreateViewModel.swift +++ b/SodaLive/Sources/Content/Create/ContentCreateViewModel.swift @@ -34,6 +34,7 @@ final class ContentCreateViewModel: ObservableObject { } @Published var isAvailableComment = true + @Published var isActiveReservation = false @Published var isAdult = false @Published var priceString = "0" { didSet { @@ -63,6 +64,20 @@ final class ContentCreateViewModel: ObservableObject { @Published var previewStartTime: String = "" @Published var previewEndTime: String = "" + @Published var releaseDateString: String = Date().convertDateFormat(dateFormat: "yyyy.MM.dd") + @Published var releaseTimeString: String = Date().convertDateFormat(dateFormat: "a hh:mm") + + var releaseDate = Date() { + willSet { + releaseDateString = newValue.convertDateFormat(dateFormat: "yyyy.MM.dd") + } + } + + var releaseTime = Date() { + willSet { + releaseTimeString = newValue.convertDateFormat(dateFormat: "a hh:mm") + } + } var placeholder = "내용을 입력하세요" @@ -75,6 +90,8 @@ final class ContentCreateViewModel: ObservableObject { detail: detail, tags: hashtags, price: price, + releaseDate: isActiveReservation ? "\(releaseDate.convertDateFormat(dateFormat: "yyyy-MM-dd")) \(releaseTime.convertDateFormat(dateFormat: "HH:mm"))" : nil, + timezone: TimeZone.current.identifier, themeId: theme!.id, isAdult: isAdult, isOnlyRental: isOnlyRental, diff --git a/SodaLive/Sources/Content/Create/CreateAudioContentRequest.swift b/SodaLive/Sources/Content/Create/CreateAudioContentRequest.swift index ca70646..ccd5712 100644 --- a/SodaLive/Sources/Content/Create/CreateAudioContentRequest.swift +++ b/SodaLive/Sources/Content/Create/CreateAudioContentRequest.swift @@ -12,6 +12,8 @@ struct CreateAudioContentRequest: Encodable { let detail: String let tags: String let price: Int + let releaseDate: String? + let timezone: String let themeId: Int let isAdult: Bool let isOnlyRental: Bool diff --git a/SodaLive/Sources/Content/Create/QuarterTimePickerView.swift b/SodaLive/Sources/Content/Create/QuarterTimePickerView.swift new file mode 100644 index 0000000..cb2e7b2 --- /dev/null +++ b/SodaLive/Sources/Content/Create/QuarterTimePickerView.swift @@ -0,0 +1,63 @@ +// +// QuarterTimePickerView.swift +// SodaLive +// +// Created by klaus on 2024/01/10. +// + +import SwiftUI + +struct QuarterTimePickerView: View { + + @Binding var selectedTime: Date + @Binding var isShowing: Bool + + var body: some View { + GeometryReader { proxy in + ZStack { + Color + .black + .opacity(0.5) + .edgesIgnoringSafeArea(.all) + + VStack(spacing: 0) { + DatePicker( + "", + selection: $selectedTime, + displayedComponents: .hourAndMinute + ) + .datePickerStyle(WheelDatePickerStyle()) + .labelsHidden() + .environment(\.locale, Locale.init(identifier: "ko")) + .frame(width: proxy.size.width - 53.4) + .onAppear { + UIDatePicker.appearance().minuteInterval = 15 + } + .onDisappear { + UIDatePicker.appearance().minuteInterval = 1 + } + + Button(action: { self.isShowing = false }) { + Text("확인") + .font(.system(size: 16)) + .foregroundColor(Color(hex: "eeeeee")) + .padding(.vertical, 10) + .frame(width: proxy.size.width) + } + } + .background(Color(hex: "222222")) + .cornerRadius(6.7) + } + .frame(width: proxy.size.width) + } + } +} + +struct QuarterTimePickerView_Previews: PreviewProvider { + static var previews: some View { + QuarterTimePickerView( + selectedTime: .constant(Date()), + isShowing: .constant(true) + ) + } +} diff --git a/SodaLive/Sources/Content/Create/SelectDatePicker.swift b/SodaLive/Sources/Content/Create/SelectDatePicker.swift new file mode 100644 index 0000000..662cd2b --- /dev/null +++ b/SodaLive/Sources/Content/Create/SelectDatePicker.swift @@ -0,0 +1,53 @@ +// +// SelectDatePicker.swift +// SodaLive +// +// Created by klaus on 2024/01/10. +// + +import SwiftUI + +struct SelectDatePicker: View { + + @Binding var selectedDate: Date + @Binding var isShowing: Bool + + var body: some View { + GeometryReader { proxy in + ZStack { + Color + .black + .opacity(0.5) + .edgesIgnoringSafeArea(.all) + + VStack(spacing: 0) { + DatePicker("", selection: $selectedDate, in: Date()..., displayedComponents: .date) + .datePickerStyle(WheelDatePickerStyle()) + .labelsHidden() + .environment(\.locale, Locale.init(identifier: "ko")) + .frame(width: proxy.size.width) + + Button(action: { self.isShowing = false }) { + Text("확인") + .font(.system(size: 16)) + .foregroundColor(Color(hex: "eeeeee")) + .padding(.vertical, 10) + .frame(width: proxy.size.width - 53.4) + } + } + .background(Color(hex: "222222")) + .cornerRadius(6.7) + } + .frame(width: proxy.size.width) + } + } +} + +struct SelectDatePicker_Previews: PreviewProvider { + static var previews: some View { + SelectDatePicker( + selectedDate: .constant(Date()), + isShowing: .constant(true) + ) + } +}