// // SignUpView.swift // SodaLive // // Created by klaus on 2023/08/09. // import SwiftUI struct SignUpView: View { enum FocusField: Hashable { case email, password } @ObservedObject var viewModel = SignUpViewModel() @StateObject var keyboardHandler = KeyboardHandler() @State private var isPasswordVisible: Bool = false @FocusState private var focusedField: FocusField? var body: some View { BaseView(isLoading: $viewModel.isLoading) { GeometryReader { proxy in VStack(spacing: 0) { DetailNavigationBar(title: "회원가입") ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 0) { TextField("이메일", text: $viewModel.email) .submitLabel(.next) .focused($focusedField, equals: .email) .autocapitalization(.none) .disableAutocorrection(true) .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(.grayee) .keyboardType(.emailAddress) .padding(.vertical, 18) .padding(.horizontal, 13.3) .frame(height: 56) .background(RoundedRectangle(cornerRadius: 6.7).fill(Color.gray33.opacity(0.7))) .padding(.horizontal, 13.3) .padding(.top, 13.3) .onSubmit { self.focusedField = .password } .onTapGesture { self.focusedField = .email } HStack { Group { if isPasswordVisible { TextField("비밀번호", text: $viewModel.password) } else { SecureField("비밀번호", text: $viewModel.password) } } .submitLabel(.done) .focused($focusedField, equals: .password) .autocapitalization(.none) .disableAutocorrection(true) .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(.grayee) Spacer() Image(systemName: isPasswordVisible ? "eye.slash.fill" : "eye.fill") .foregroundColor(.grayee) .onTapGesture { hideKeyboard() isPasswordVisible.toggle() } } .padding(.vertical, 18) .padding(.horizontal, 13.3) .frame(height: 56) .background(RoundedRectangle(cornerRadius: 6.7).fill(Color.gray33.opacity(0.7))) .padding(.horizontal, 13.3) .padding(.top, 16) .onTapGesture { self.focusedField = .password } VStack(spacing: 5) { HStack(spacing: 10) { Image( viewModel.isAgreeTerms ? "btn_select_checked" : "btn_select_normal" ) .padding(10) .onTapGesture { hideKeyboard() viewModel.isAgreeTerms.toggle() } HStack(spacing: 5) { Text("이용약관") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color.grayee) Text("(필수)") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color.button) } .onTapGesture { AppState.shared.setAppStep(step: .terms) } Spacer() } .contentShape(Rectangle()) .onTapGesture { hideKeyboard() viewModel.isAgreeTerms.toggle() } HStack(spacing: 10) { Image( viewModel.isAgreePrivacyPolicy ? "btn_select_checked" : "btn_select_normal" ) .padding(10) .onTapGesture { hideKeyboard() viewModel.isAgreePrivacyPolicy.toggle() } HStack(spacing: 5) { Text("개인정보수집 및 이용동의") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color.grayee) Text("(필수)") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color.button) } .onTapGesture { AppState.shared.setAppStep(step: .privacy) } Spacer() } .contentShape(Rectangle()) .onTapGesture { hideKeyboard() viewModel.isAgreePrivacyPolicy.toggle() } } .padding(.top, 20) .padding(.horizontal, 13.3) Text("회원가입") .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(Color.white) .padding(.vertical, 16) .frame(maxWidth: .infinity) .background(Color.button) .cornerRadius(10) .padding(.horizontal, 13.3) .contentShape(Rectangle()) .onTapGesture { hideKeyboard() viewModel.signUp() } .padding(.top, 26.7) Rectangle() .foregroundColor(Color.black) .frame(width: screenSize().width, height: keyboardHandler.keyboardHeight) if proxy.safeAreaInsets.bottom > 0 { Rectangle() .foregroundColor(Color.black) .frame(width: proxy.size.width, height: 15.3) } } } } .edgesIgnoringSafeArea(.bottom) .onAppear { focusedField = .email } .onTapGesture { hideKeyboard() } } } .popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) { GeometryReader { geo in HStack { Spacer() Text(viewModel.errorMessage) .padding(.vertical, 13.3) .padding(.horizontal, 6.7) .frame(width: geo.size.width - 66.7, alignment: .center) .font(.custom(Font.medium.rawValue, size: 12)) .background(Color.button) .foregroundColor(Color.white) .multilineTextAlignment(.leading) .fixedSize(horizontal: false, vertical: true) .cornerRadius(20) .padding(.top, 66.7) Spacer() } } } } } struct SignUpView_Previews: PreviewProvider { static var previews: some View { SignUpView() } }