forked from AcaMate/AcaMate_iOS
[✨] 드롭다운 최종 완성, 커스텀 텍스트 필드 전체 변경, 회원가입 로직 추가 중
This commit is contained in:
parent
4875427e24
commit
63031172a1
Binary file not shown.
|
@ -45,6 +45,7 @@ struct CircleBtnView: View {
|
||||||
}
|
}
|
||||||
.frame(width: state.width, height: state.height)
|
.frame(width: state.width, height: state.height)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
endTextEditing()
|
||||||
guard let action = state.action else {return}
|
guard let action = state.action else {return}
|
||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct SimpleBtnView: View {
|
||||||
.frame(width: state.width, height: state.height)
|
.frame(width: state.width, height: state.height)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if state.isUsable {
|
if state.isUsable {
|
||||||
|
endTextEditing()
|
||||||
guard let action = state.action else { return }
|
guard let action = state.action else { return }
|
||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
|
@ -30,6 +31,7 @@ struct SimpleBtnView: View {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Button{
|
Button{
|
||||||
|
endTextEditing()
|
||||||
guard let action = state.action else { return }
|
guard let action = state.action else { return }
|
||||||
action()
|
action()
|
||||||
} label: {
|
} label: {
|
||||||
|
|
|
@ -13,9 +13,10 @@ class DropdownManager: ObservableObject {
|
||||||
@Published var anchor: CGRect = .zero
|
@Published var anchor: CGRect = .zero
|
||||||
@Published var font: Font = .body
|
@Published var font: Font = .body
|
||||||
|
|
||||||
var onSelect: ((String) -> Void)?
|
var onSelect: ((Int) -> Void)?
|
||||||
|
|
||||||
func show(items: [String], anchor: CGRect, onSelect: @escaping (String) -> Void) {
|
func show(items: [String], anchor: CGRect,
|
||||||
|
onSelect: @escaping (Int) -> Void) {
|
||||||
self.items = items
|
self.items = items
|
||||||
self.anchor = anchor
|
self.anchor = anchor
|
||||||
self.onSelect = onSelect
|
self.onSelect = onSelect
|
||||||
|
@ -32,22 +33,28 @@ class DropdownManager: ObservableObject {
|
||||||
struct DropdownButton: View {
|
struct DropdownButton: View {
|
||||||
@ObservedObject var manager: DropdownManager
|
@ObservedObject var manager: DropdownManager
|
||||||
@State var title: String
|
@State var title: String
|
||||||
|
|
||||||
|
var onSelect: ((Int) -> Void)?
|
||||||
let items: [String]
|
let items: [String]
|
||||||
|
|
||||||
|
|
||||||
init(manager: DropdownManager, title: String, items: [String]) {
|
init(manager: DropdownManager, title: String, items: [String],
|
||||||
|
onSelect: @escaping (Int) -> Void) {
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.title = title
|
self.title = title
|
||||||
self.items = items
|
self.items = items
|
||||||
|
self.onSelect = onSelect
|
||||||
}
|
}
|
||||||
|
|
||||||
@State private var frame: CGRect = .zero
|
@State private var frame: CGRect = .zero
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button {
|
Button {
|
||||||
manager.show(items: items, anchor: frame) { selected in
|
endTextEditing()
|
||||||
print("선택한 항목:", selected)
|
manager.show(items: items, anchor: frame) { index in
|
||||||
title = selected
|
self.onSelect?(index)
|
||||||
|
print("선택한 항목: \(items[index])")
|
||||||
|
title = items[index]
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
|
@ -62,7 +69,10 @@ struct DropdownButton: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(4)
|
.padding(4)
|
||||||
.background(RoundedRectangle(cornerRadius: 8).stroke(Color(.Normal.normal)))
|
.background{
|
||||||
|
RoundedRectangle(cornerRadius: 8)
|
||||||
|
.fill(Color.clear)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.background(
|
.background(
|
||||||
|
@ -131,16 +141,16 @@ struct GlobalDropdownOverlay: View {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
ForEach(Array(manager.items.enumerated()), id: \.offset) { index, item in
|
ForEach(Array(manager.items.enumerated()), id: \.offset) { index, item in
|
||||||
Button {
|
Button {
|
||||||
manager.onSelect?(item)
|
manager.onSelect?(index)
|
||||||
manager.dismiss()
|
manager.dismiss()
|
||||||
} label: {
|
} label: {
|
||||||
Text(item)
|
Text(item)
|
||||||
.font(manager.font)
|
.font(manager.font)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.minimumScaleFactor(0.5)
|
.minimumScaleFactor(0.4)
|
||||||
|
.padding([.leading, .trailing], 8)
|
||||||
.frame(maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)
|
.frame(maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)
|
||||||
.padding([.leading,.trailing], 2)
|
.contentShape(Rectangle())
|
||||||
.contentShape(Rectangle())
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,10 @@ struct RegisterView: View {
|
||||||
@StateObject var btnVM = ButtonViewModel()
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
@StateObject var registerVM: RegisterViewModel
|
@StateObject var registerVM: RegisterViewModel
|
||||||
|
|
||||||
private let responseValue: (SNSLoginType, String)
|
// private let responseValue: (SNSLoginType, String)
|
||||||
|
|
||||||
init(_ appVM: AppViewModel, type: SNSLoginType, snsID: String) {
|
init(_ appVM: AppViewModel, type: SNSLoginType, snsID: String) {
|
||||||
_registerVM = StateObject(wrappedValue: RegisterViewModel(appVM))
|
_registerVM = StateObject(wrappedValue: RegisterViewModel(appVM, type: type, snsID: snsID))
|
||||||
self.responseValue.0 = type
|
|
||||||
self.responseValue.1 = snsID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,11 +28,9 @@ struct RegisterView: View {
|
||||||
|
|
||||||
@StateObject private var dropdownManager = DropdownManager()
|
@StateObject private var dropdownManager = DropdownManager()
|
||||||
|
|
||||||
private let addressBtnID = UUID()
|
|
||||||
private let registerBtnID = UUID()
|
|
||||||
|
|
||||||
@State private var selected = ""
|
@State private var onDomainTxf = false
|
||||||
let options = ["Swift", "Kotlin", "Dart", "JavaScript", "C#","C++","C"]
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
// MARK: TO-DO
|
// MARK: TO-DO
|
||||||
|
@ -67,13 +63,13 @@ struct RegisterView: View {
|
||||||
.frame(width: 60, alignment: .center)
|
.frame(width: 60, alignment: .center)
|
||||||
.padding(.trailing,12)
|
.padding(.trailing,12)
|
||||||
Spacer(minLength: 1)
|
Spacer(minLength: 1)
|
||||||
CustomTextField(placeholder: "최대 10글자 입력", text: $registerVM.nameText, alignment: .center)
|
CustomTxfView(placeholder: "이름 입력 (10 글자)", text: $registerVM.nameText, maxLength: 10, alignment: .center)
|
||||||
.frame(maxWidth: .infinity,maxHeight: 48)
|
.frame(maxWidth: .infinity,maxHeight: 48)
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
.background {
|
.background {
|
||||||
RoundedRectangle(cornerRadius: 24)
|
RoundedRectangle(cornerRadius: 24)
|
||||||
.foregroundStyle(Color(.Normal.light))
|
.foregroundStyle(Color(.Normal.light))
|
||||||
}
|
}.clipped()
|
||||||
}
|
}
|
||||||
.padding(EdgeInsets(top: 8, leading: 16, bottom: 16, trailing: 16))
|
.padding(EdgeInsets(top: 8, leading: 16, bottom: 16, trailing: 16))
|
||||||
|
|
||||||
|
@ -103,37 +99,48 @@ struct RegisterView: View {
|
||||||
.frame(width: 60, alignment: .center)
|
.frame(width: 60, alignment: .center)
|
||||||
.padding(.trailing,12)
|
.padding(.trailing,12)
|
||||||
Spacer(minLength: 1)
|
Spacer(minLength: 1)
|
||||||
CustomTextField(placeholder: "앞부분 입력", text: $registerVM.emailFrontText, alignment: .center)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 24)
|
|
||||||
.foregroundStyle(Color(.Normal.light))
|
|
||||||
}
|
|
||||||
// Spacer(minLength: 1)
|
|
||||||
Text("@")
|
|
||||||
.font(.nps(size: 16))
|
|
||||||
.padding([.leading, .trailing], 4)
|
|
||||||
// Spacer(minLength: 1)
|
|
||||||
|
|
||||||
DropdownButton(manager: dropdownManager, title: "도메인 선택",
|
VStack (spacing: 4) {
|
||||||
items: registerVM.emailTailList)
|
CustomTxfView(placeholder: "이메일 입력(30 글자)", text: $registerVM.emailFrontText, maxLength: 30, alignment: .center)
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background {
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
RoundedRectangle(cornerRadius: 24)
|
.background {
|
||||||
.foregroundStyle(Color(.Normal.light))
|
RoundedRectangle(cornerRadius: 24)
|
||||||
}
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
}
|
||||||
|
|
||||||
// 직접 입력 선택시 나오게 할 부분
|
HStack(spacing: 0) {
|
||||||
/*
|
Text("@")
|
||||||
CustomTextField(placeholder: "뒷부분 입력", text: $registerVM.emailFrontText, alignment: .center)
|
.font(.nps(size: 16))
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.padding([.leading, .trailing], 4)
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
// Spacer(minLength: 1)
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 24)
|
DropdownButton(manager: dropdownManager, title: "도메인 선택",
|
||||||
.foregroundStyle(Color(.Normal.light))
|
items: registerVM.emailTailList){ index in
|
||||||
|
if registerVM.emailTailList.count-1 == index {
|
||||||
|
onDomainTxf = true
|
||||||
|
} else {
|
||||||
|
registerVM.emailTailText = registerVM.emailTailList[index]
|
||||||
|
onDomainTxf = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 24)
|
||||||
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
if onDomainTxf {
|
||||||
|
CustomTxfView(placeholder: "도메인 직접 입력(30 글자)", text: $registerVM.emailTailText, maxLength: 30, alignment: .center)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 24)
|
||||||
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
|
@ -148,26 +155,20 @@ struct RegisterView: View {
|
||||||
}
|
}
|
||||||
.frame(width: 60, alignment: .center)
|
.frame(width: 60, alignment: .center)
|
||||||
.padding(.trailing,12)
|
.padding(.trailing,12)
|
||||||
// DropdownButton(manager: dropdownManager, title: "선택", items: options)
|
DropdownButton(manager: dropdownManager, title: "선택", items: registerVM.numberHeadList){ index in
|
||||||
// CustomTextField(placeholder: "000", text: $registerVM.nameText, alignment: .center)
|
registerVM.phoneTextSet.0 = registerVM.numberHeadList[index]
|
||||||
// .frame(maxWidth: .infinity,maxHeight: 48)
|
}
|
||||||
// .padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
.background {
|
||||||
// .background {
|
RoundedRectangle(cornerRadius: 24)
|
||||||
// RoundedRectangle(cornerRadius: 24)
|
.foregroundStyle(Color(.Normal.light))
|
||||||
// .foregroundStyle(Color(.Normal.light))
|
}
|
||||||
// }
|
|
||||||
DropdownButton(manager: dropdownManager, title: "선택", items: registerVM.numberHeadList)
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 24)
|
|
||||||
.foregroundStyle(Color(.Normal.light))
|
|
||||||
}
|
|
||||||
Text("-")
|
Text("-")
|
||||||
.font(.nps(size: 16))
|
.font(.nps(size: 16))
|
||||||
.padding([.leading, .trailing], 4)
|
.padding([.leading, .trailing], 4)
|
||||||
|
|
||||||
CustomTextField(placeholder: "0000", text: $registerVM.nameText, alignment: .center)
|
CustomTxfView(placeholder: "0000", text: $registerVM.phoneTextSet.1, maxLength: 4, alignment: .center)
|
||||||
.frame(maxWidth: .infinity,maxHeight: 48)
|
.frame(maxWidth: .infinity,maxHeight: 48)
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
.background {
|
.background {
|
||||||
RoundedRectangle(cornerRadius: 24)
|
RoundedRectangle(cornerRadius: 24)
|
||||||
.foregroundStyle(Color(.Normal.light))
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
@ -175,9 +176,9 @@ struct RegisterView: View {
|
||||||
Text("-")
|
Text("-")
|
||||||
.font(.nps(size: 16))
|
.font(.nps(size: 16))
|
||||||
.padding([.leading, .trailing], 4)
|
.padding([.leading, .trailing], 4)
|
||||||
CustomTextField(placeholder: "0000", text: $registerVM.nameText, alignment: .center)
|
CustomTxfView(placeholder: "0000", text: $registerVM.phoneTextSet.2, maxLength: 4, alignment: .center)
|
||||||
.frame(maxWidth: .infinity,maxHeight: 48)
|
.frame(maxWidth: .infinity, maxHeight: 48)
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
.background {
|
.background {
|
||||||
RoundedRectangle(cornerRadius: 24)
|
RoundedRectangle(cornerRadius: 24)
|
||||||
.foregroundStyle(Color(.Normal.light))
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
@ -185,31 +186,44 @@ struct RegisterView: View {
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
HStack(spacing: 0){
|
HStack(alignment: .center, spacing: 0){
|
||||||
Text("주소")
|
Text("주소")
|
||||||
.font(.nps(size: 16))
|
.font(.nps(size: 16))
|
||||||
.frame(width: 60, alignment: .center)
|
.frame(width: 60, alignment: .center)
|
||||||
.padding(.trailing,12)
|
.padding(.trailing,12)
|
||||||
Spacer(minLength: 1)
|
|
||||||
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
SimpleBtnView(vm: btnVM, id: addressBtnID)
|
SimpleBtnView(vm: btnVM, id: registerVM.addressBtnID)
|
||||||
.padding(.bottom, isSelectAddr ? 4:0)
|
.frame(maxWidth: .infinity, maxHeight: 48)
|
||||||
CustomTextField(placeholder: "상세 주소 입력", text: $registerVM.addrDetailText, alignment: .center)
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
.frame(maxWidth: .infinity,
|
|
||||||
maxHeight: isSelectAddr ? 48 : 0)
|
|
||||||
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
|
|
||||||
.background {
|
.background {
|
||||||
RoundedRectangle(cornerRadius: 24)
|
RoundedRectangle(cornerRadius: 24)
|
||||||
.foregroundStyle(Color(.Normal.light))
|
.foregroundStyle(Color(.Normal.light))
|
||||||
}
|
}
|
||||||
.opacity(isSelectAddr ? 1.0 : 0.0)
|
.padding(.bottom, isSelectAddr ? 4:0)
|
||||||
|
if isSelectAddr {
|
||||||
|
CustomTxfView(placeholder: "상세 주소 입력 (50 글자)", text: $registerVM.addrDetailText, maxLength: 50, alignment: .center)
|
||||||
|
.frame(maxWidth: .infinity,
|
||||||
|
maxHeight: isSelectAddr ? 48 : 0)
|
||||||
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 24)
|
||||||
|
.foregroundStyle(Color(.Normal.light))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
// .background(Color(.Normal.light))
|
|
||||||
|
SimpleBtnView(vm: btnVM, id: registerVM.registerBtnID)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: 48)
|
||||||
|
.padding(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
|
||||||
|
// .background {
|
||||||
|
// RoundedRectangle(cornerRadius: 24)
|
||||||
|
// .foregroundStyle(Color(.Normal.light))
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
GlobalDropdownOverlay(manager: dropdownManager)
|
GlobalDropdownOverlay(manager: dropdownManager)
|
||||||
}
|
}
|
||||||
|
@ -221,30 +235,36 @@ struct RegisterView: View {
|
||||||
if let result = result as? (String, String) {
|
if let result = result as? (String, String) {
|
||||||
print(result.0)
|
print(result.0)
|
||||||
isSelectAddr = true
|
isSelectAddr = true
|
||||||
// printLog(registerVM.addressText)
|
|
||||||
registerVM.addressText = result.0
|
registerVM.addressText = result.0
|
||||||
|
|
||||||
btnVM.setSize(for: addressBtnID, newWidth: .infinity, newHeight: .infinity)
|
btnVM.setSize(for: registerVM.addressBtnID, newWidth: .infinity, newHeight: .infinity)
|
||||||
// printLog(registerVM.addressText)
|
btnVM.setText(for: registerVM.addressBtnID, newText: "\(registerVM.addressText)", newFont: .nps(size: 16))
|
||||||
btnVM.setText(for: addressBtnID, newText: "\(registerVM.addressText)", newFont: .nps(size: 16))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
topVM.titleName = "회원가입"
|
topVM.titleName = "회원가입"
|
||||||
|
|
||||||
topVM.setLeftBtn(Image(.Icon.left), size: CGPoint(x: 40, y: 40), action: leftAct)
|
topVM.setLeftBtn(Image(.Icon.left), size: CGPoint(x: 40, y: 40), action: leftAct)
|
||||||
topVM.setRightBtn(size: CGPoint(x: 40, y: 40), action: rightAct)
|
topVM.setRightBtn(size: CGPoint(x: 40, y: 40), action: rightAct)
|
||||||
|
|
||||||
btnVM.setSize(for: addressBtnID, newWidth: 80, newHeight: 24)
|
btnVM.setSize(for: registerVM.addressBtnID, newWidth: 80, newHeight: 24)
|
||||||
btnVM.setText(for: addressBtnID, newText: "\(registerVM.addressText)", newFont: .nps(size: 16))
|
btnVM.setText(for: registerVM.addressBtnID, newText: "\(registerVM.addressText)", newFont: .nps(size: 16))
|
||||||
btnVM.setAction(for: addressBtnID) {
|
btnVM.setTextColor(for: registerVM.addressBtnID, newColor: Color.Text.black)
|
||||||
self.showWebView.toggle()
|
btnVM.setAction(for: registerVM.addressBtnID) { self.showWebView.toggle() }
|
||||||
}
|
|
||||||
|
btnVM.setSize(for: registerVM.registerBtnID, newWidth: .infinity, newHeight: 48)
|
||||||
|
btnVM.setText(for: registerVM.registerBtnID, newText: "회원가입", newFont: .nps(font: .bold, size: 24))
|
||||||
|
btnVM.setTextColor(for: registerVM.registerBtnID, newColor: Color.Point.dark)
|
||||||
|
btnVM.setAction(for: registerVM.registerBtnID) { registerVM.registerUser() }
|
||||||
|
|
||||||
|
|
||||||
dropdownManager.font = .nps(size: 16)
|
dropdownManager.font = .nps(size: 16)
|
||||||
}
|
}
|
||||||
.onChange(of: registerVM.addressText) { _, new in
|
// .onChange(of: dropdownManager.onSelect) { _, new in
|
||||||
|
// printLog("CHANGE: \(new)")
|
||||||
}
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func leftAct() {
|
func leftAct() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ class AppViewModel: ObservableObject {
|
||||||
@Published var menuName: MenuName = .Home
|
@Published var menuName: MenuName = .Home
|
||||||
@Published var naviState: NaviState = .init(act: .NONE, path: .Intro)
|
@Published var naviState: NaviState = .init(act: .NONE, path: .Intro)
|
||||||
|
|
||||||
var alertData: AlertData = .init(body: "")
|
@Published var alertData: AlertData = .init(body: "")
|
||||||
|
|
||||||
/// 항상 최신값을 가지고 있다가 구독자 추가 되면 그 즉시 값을 전달하고 이후 업데이트 되는 값을 계속 보내주는 역할을 함
|
/// 항상 최신값을 가지고 있다가 구독자 추가 되면 그 즉시 값을 전달하고 이후 업데이트 되는 값을 계속 보내주는 역할을 함
|
||||||
let alertAction = CurrentValueSubject<String?, Never>(nil)
|
let alertAction = CurrentValueSubject<String?, Never>(nil)
|
||||||
|
|
|
@ -9,24 +9,38 @@ import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
class RegisterViewModel: ObservableObject {
|
class RegisterViewModel: ObservableObject {
|
||||||
private let appVM: AppViewModel
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
private let appVM: AppViewModel
|
||||||
|
private let responseValue: (SNSLoginType, String)
|
||||||
|
|
||||||
init(_ appVM: AppViewModel) {
|
init(_ appVM: AppViewModel, type: SNSLoginType, snsID: String) {
|
||||||
self.appVM = appVM
|
self.appVM = appVM
|
||||||
|
self.responseValue = (type, snsID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@State var selectDate: Date = {
|
let addressBtnID = UUID()
|
||||||
let calendar = Calendar.current
|
let registerBtnID = UUID()
|
||||||
return calendar.date(byAdding: .year, value: -12, to: Date()) ?? Date()
|
|
||||||
}()
|
|
||||||
|
|
||||||
@State var nameText: String = ""
|
@Published var selectDate: Date = {
|
||||||
@State var emailFrontText: String = ""
|
let calendar = Calendar.current
|
||||||
@State var emailTailText: String = ""
|
return calendar.date(byAdding: .year, value: 0, to: Date()) ?? Date()
|
||||||
@State var phoneArray: [Int] = []
|
}() {
|
||||||
|
didSet {
|
||||||
|
if selectDate != oldValue {
|
||||||
|
changeDate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Published var changeDate: Bool = false
|
||||||
|
|
||||||
|
@Published var nameText: String = ""
|
||||||
|
@Published var emailFrontText: String = ""
|
||||||
|
@Published var emailTailText: String = ""
|
||||||
|
@Published var numberHead: String = ""
|
||||||
|
@Published var phoneTextSet: (String,String,String) = ("","","")
|
||||||
@Published var addressText: String = "주소 입력"
|
@Published var addressText: String = "주소 입력"
|
||||||
@State var addrDetailText: String = ""
|
@Published var addrDetailText: String = ""
|
||||||
|
|
||||||
let numberHeadList = ["010","011","016","017","018","019"]
|
let numberHeadList = ["010","011","016","017","018","019"]
|
||||||
let emailTailList = ["gmail.com",
|
let emailTailList = ["gmail.com",
|
||||||
|
@ -41,4 +55,30 @@ class RegisterViewModel: ObservableObject {
|
||||||
"protonmail.com",
|
"protonmail.com",
|
||||||
"직접 입력"]
|
"직접 입력"]
|
||||||
|
|
||||||
|
func registerUser() {
|
||||||
|
// 필수 값
|
||||||
|
|
||||||
|
if nameText != "" && emailFrontText != "" && emailTailText != "" && phoneTextSet.0 != "" && phoneTextSet.1 != "" && phoneTextSet.2 != "" {
|
||||||
|
if !changeDate || addressText == "주소 입력" {
|
||||||
|
appVM.alertData = AlertData(
|
||||||
|
title: "알림",
|
||||||
|
body: "\(changeDate ? "":"[생일]")\((addressText != "주소 입력") ? "":"[주소]")의 내용이 없습니다.\n 계속해서 진행할까요?",
|
||||||
|
button: [ButtonType(name: "확인", role: .cancel, function: nil)])
|
||||||
|
appVM.showAlert.toggle()
|
||||||
|
// 넘어가는 로직도 추가
|
||||||
|
} else {
|
||||||
|
//정상 동작
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appVM.alertData = AlertData(
|
||||||
|
title: "경고", body: "필수 입력 사항이 누락되었습니다.",
|
||||||
|
button: [ButtonType(name: "확인", role: .cancel, function: nil)])
|
||||||
|
appVM.showAlert.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,69 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
struct CustomTextField: UIViewRepresentable {
|
struct FixedSizeWrapper<Content: UIView>: UIViewRepresentable {
|
||||||
|
let content: () -> Content
|
||||||
|
let width: CGFloat
|
||||||
|
let height: CGFloat
|
||||||
|
|
||||||
|
func makeUIView(context: Context) -> Content {
|
||||||
|
let view = content()
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
view.widthAnchor.constraint(equalToConstant: width),
|
||||||
|
view.heightAnchor.constraint(equalToConstant: height)
|
||||||
|
])
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: Content, context: Context) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomTxfView: View {
|
||||||
|
|
||||||
var placeholder: String
|
var placeholder: String
|
||||||
@Binding var text: String
|
@Binding var text: String
|
||||||
|
|
||||||
|
var maxLength: Int = 100
|
||||||
|
var isSecure: Binding<Bool> = .constant(false)
|
||||||
|
var alignment: TextAlignment = .leading
|
||||||
|
|
||||||
|
var textColor = Color(.Text.detail)
|
||||||
|
var font: Font = .nps(size:16)
|
||||||
|
// UIFont(name: "NPS-font-Regular", size: 16)
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
TextField(placeholder, text: $text)
|
||||||
|
// Binding<String>(
|
||||||
|
// get: { text },
|
||||||
|
// set: { newValue in
|
||||||
|
// text = String(newValue.prefix(maxLength))
|
||||||
|
// }
|
||||||
|
// ))
|
||||||
|
.font(font)
|
||||||
|
.tint(textColor)
|
||||||
|
.lineLimit(1)
|
||||||
|
.multilineTextAlignment(alignment)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
.clipped()
|
||||||
|
|
||||||
|
.onChange(of: text) { old, new in
|
||||||
|
if new.count > maxLength {
|
||||||
|
text = String(new.prefix(maxLength))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CustomTextField: UIViewRepresentable {
|
||||||
|
var placeholder: String
|
||||||
|
@Binding var text: String
|
||||||
|
var maxLength: Int?
|
||||||
var isSecure: Binding<Bool> = .constant(false)
|
var isSecure: Binding<Bool> = .constant(false)
|
||||||
|
|
||||||
var textColor = UIColor(Color(.Text.detail))
|
var textColor = UIColor(Color(.Text.detail))
|
||||||
|
@ -21,24 +80,31 @@ struct CustomTextField: UIViewRepresentable {
|
||||||
// [필수] 초기화 시 UIView 생성
|
// [필수] 초기화 시 UIView 생성
|
||||||
func makeUIView(context: Context) -> UITextField {
|
func makeUIView(context: Context) -> UITextField {
|
||||||
let txf = UITextField()
|
let txf = UITextField()
|
||||||
// txf.placeholder = placeholder
|
|
||||||
txf.attributedPlaceholder = NSAttributedString(string: "\(placeholder)", attributes: [NSAttributedString.Key.foregroundColor : UIColor(.Text.border)])
|
|
||||||
|
// txf.placeholder = placeholder
|
||||||
|
txf.attributedPlaceholder = NSAttributedString(
|
||||||
|
string: "\(placeholder)",
|
||||||
|
attributes: [NSAttributedString.Key.foregroundColor : UIColor(.Text.border)])
|
||||||
|
|
||||||
txf.isSecureTextEntry = isSecure.wrappedValue
|
txf.isSecureTextEntry = isSecure.wrappedValue
|
||||||
|
|
||||||
|
txf.adjustsFontSizeToFitWidth = true
|
||||||
|
txf.minimumFontSize = 4
|
||||||
|
|
||||||
txf.textColor = textColor
|
txf.textColor = textColor
|
||||||
txf.font = font
|
|
||||||
|
|
||||||
txf.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
|
|
||||||
let height = (font?.lineHeight ?? 10) + 8
|
let height = (font?.lineHeight ?? 10) + 8
|
||||||
txf.frame.size.height = height
|
txf.frame.size.height = height
|
||||||
|
|
||||||
|
txf.borderStyle = .none
|
||||||
txf.autocorrectionType = .no
|
txf.autocorrectionType = .no
|
||||||
txf.autocapitalizationType = .none
|
txf.autocapitalizationType = .none
|
||||||
txf.smartInsertDeleteType = .no
|
txf.smartInsertDeleteType = .no
|
||||||
txf.textContentType = .oneTimeCode
|
txf.textContentType = .oneTimeCode
|
||||||
txf.textAlignment = self.alignment
|
txf.textAlignment = self.alignment
|
||||||
|
txf.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
txf.setContentHuggingPriority(.required, for: .horizontal)
|
||||||
|
txf.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||||
|
|
||||||
txf.delegate = context.coordinator
|
txf.delegate = context.coordinator
|
||||||
return txf
|
return txf
|
||||||
|
@ -51,19 +117,34 @@ struct CustomTextField: UIViewRepresentable {
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
func makeCoordinator() -> Coordinator {
|
||||||
Coordinator(self)
|
Coordinator(self, max: maxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Coordinator: NSObject, UITextFieldDelegate {
|
class Coordinator: NSObject, UITextFieldDelegate {
|
||||||
var parent: CustomTextField
|
var parent: CustomTextField
|
||||||
|
var maxLength: Int?
|
||||||
|
|
||||||
init(_ parent: CustomTextField) {
|
init(_ parent: CustomTextField, max: Int?) {
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.maxLength = max
|
||||||
}
|
}
|
||||||
|
|
||||||
func textFieldDidChangeSelection(_ textField: UITextField) {
|
func textFieldDidChangeSelection(_ textField: UITextField) {
|
||||||
parent.text = textField.text ?? ""
|
parent.text = textField.text ?? ""
|
||||||
}
|
}
|
||||||
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
let current = textField.text ?? ""
|
||||||
|
guard let stringRange = Range(range, in: current) else { return false}
|
||||||
|
let updated = current.replacingCharacters(in: stringRange, with: string)
|
||||||
|
return updated.count <= (maxLength ?? 9999)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
// let currentText = textField.text ?? ""
|
||||||
|
// guard let stringRange = Range(range, in: currentText) else { return false }
|
||||||
|
// let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
|
||||||
|
// return updatedText.count <= maxLength
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user