[] 회원가입 화면 추가 및 몇가지 동작 로직 수정

This commit is contained in:
김선규 2025-03-24 17:53:48 +09:00
parent 45a28e386d
commit 5a2c237e3a
17 changed files with 297 additions and 63 deletions

View File

@ -0,0 +1,78 @@
//
// WebView.swift
// AcaMate
//
// Created by TAnine on 3/24/25.
//
import SwiftUI
import WebKit
struct WebView: UIViewControllerRepresentable {
@Binding var isLoding: Bool
func updateUIViewController(_ uiViewController: WebViewController, context: Context) {
}
func makeUIViewController(context: Context) -> WebViewController {
return WebViewController()
}
}
class WebViewController: UIViewController, WKUIDelegate {
override func viewDidLoad() {
super.viewDidLoad()
webView()
}
func webView() {
let url = URL(string: "https://sean-59.github.io/Kakao-Postcode/")!
let request = URLRequest(url: url)
let configuration = WKWebViewConfiguration()
let contentController = WKUserContentController()
contentController.add(self, name: "callBackHandler")
configuration.userContentController = contentController
let webview = WKWebView(frame: view.bounds, configuration: configuration)
webview.uiDelegate = self
webview.navigationDelegate = self
webview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webview.isUserInteractionEnabled = true
webview.scrollView.isUserInteractionEnabled = true
webview.scrollView.delaysContentTouches = false
webview.load(request)
view.addSubview(webview)
}
}
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("웹뷰 로딩 시작")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("웹뷰 로딩 완료")
// (: ) .
}
}
extension WebViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
if let data = message.body as? [String: Any] {
print(data)
print(data["jibunAddress"] ?? "jibunAddress 없음")
print(data["roadAddress"] ?? "roadAddress 없음")
print(data["zonecode"] ?? "zonecode 없음")
}
}
}

View File

@ -22,13 +22,13 @@ struct NavigationView: View {
case .NONE:
EmptyView()
case .Intro:
IntroView(appVM: appVM)
IntroView(appVM)
case .Login :
LoginView(appVM: appVM)
LoginView(appVM)
case .Register(let type, let id):
RegisterView(type: type, snsID: id)
RegisterView(appVM, type: type, snsID: id)
case .SelectAcademy:
SelectAcademyView()
SelectAcademyView(appVM)
case .Main:
MainView()
case .ChatRoom(let id):

View File

@ -8,15 +8,14 @@
import SwiftUI
import Combine
struct IntroView: View {
// @EnvironmentObject var appVM: AppViewModel
@StateObject private var introVM : IntroViewModel
struct IntroView: View {
@EnvironmentObject var appVM: AppViewModel
@StateObject var introVM: IntroViewModel
@State var cancellables: Set<AnyCancellable> = []
init(appVM: AppViewModel){
_introVM = StateObject(wrappedValue: IntroViewModel(appVM: appVM))
// self.introVM = IntroViewModel(appVM: appVM)
init(_ appVM: AppViewModel) {
_introVM = StateObject(wrappedValue: IntroViewModel(appVM))
}
var body: some View {

View File

@ -8,13 +8,16 @@
import SwiftUI
import Combine
struct LoginView: View {
// @EnvironmentObject var appVM: AppViewModel
@StateObject private var loginVM: LoginViewModel
init(appVM : AppViewModel) {
_loginVM = StateObject(wrappedValue: LoginViewModel(appVM: appVM))
@EnvironmentObject var appVM: AppViewModel
@StateObject var loginVM: LoginViewModel
init(_ appVM: AppViewModel) {
_loginVM = StateObject(wrappedValue: LoginViewModel(appVM))
}
var body: some View {
VStack(spacing: 0) {
Spacer().frame(height: 100)
@ -54,6 +57,9 @@ struct LoginView: View {
}
.frame(maxWidth: .infinity,maxHeight: .infinity)
.fullDrawView(.Normal.normal)
.onAppear() {
}
// .onChange(of: loginVM.pathName){ _, new in
// appVM.naviState.set(act: .ADD, path: new)

View File

@ -11,37 +11,146 @@ struct RegisterView: View {
@EnvironmentObject var appVM: AppViewModel
@StateObject private var topVM = TopViewModel()
@StateObject var btnVM = ButtonViewModel()
@StateObject var registerVM: RegisterViewModel
private let responseValue: (SNSLoginType, String)
init(_ appVM: AppViewModel, type: SNSLoginType, snsID: String) {
_registerVM = StateObject(wrappedValue: RegisterViewModel(appVM))
self.responseValue.0 = type
self.responseValue.1 = snsID
}
@State private var scrollOffset: CGPoint = .zero
@State private var showWebView = false
let type: SNSLoginType
let snsID: String
@State private var selectDate: Date = {
let calendar = Calendar.current
return calendar.date(byAdding: .year, value: -12, to: Date()) ?? Date()
}()
let addressBtnID = UUID()
let registerBtnID = UUID()
var body: some View {
// MARK: TO-DO
//
// , , , ,
VStack(spacing: 0) {
TopView(topVM: topVM)
OffsetObservableScrollView(showsIndicators: false, scrollOffset: $scrollOffset) { proxy in
DatePicker("생년월일 입력", selection: $selectDate, displayedComponents: [.date])
//
HStack(spacing: 0){
HStack(spacing: 0) {
Text("이름")
.font(.nps(size: 16))
Text("*")
.font(.nps(size: 16))
.foregroundStyle(Color(.Other.red))
}
.frame(width: 60, alignment: .leading)
Spacer(minLength: 1)
CustomTextField(placeholder: "최대 10글자", text: $registerVM.nameText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
}
.padding()
//
DatePicker("생일", selection: $registerVM.selectDate, displayedComponents: [.date])
.datePickerStyle(.compact)
.environment(\.locale, Locale(identifier: "ko_KR"))
.font(.nps(size: 16))
.padding()
// E-Mail
HStack(spacing: 0){
Text("이메일")
.font(.nps(size: 16))
.frame(width: 60, alignment: .leading)
Spacer(minLength: 1)
CustomTextField(placeholder: "앞부분 입력", text: $registerVM.emailFrontText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
// Spacer(minLength: 1)
Text("@")
.font(.nps(font: .bold, size: 16))
.padding([.leading, .trailing], 4)
// Spacer(minLength: 1)
CustomTextField(placeholder: "뒷부분 입력", text: $registerVM.emailTailText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
}
.padding()
// Phone
HStack(spacing: 0){
Text("연락처")
.font(.nps(size: 16))
.frame(width: 60, alignment: .leading)
CustomTextField(placeholder: "000", text: $registerVM.nameText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
Text("-")
.font(.nps(size: 16))
.padding([.leading, .trailing], 4)
CustomTextField(placeholder: "0000", text: $registerVM.nameText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
Text("-")
.font(.nps(size: 16))
.padding([.leading, .trailing], 4)
CustomTextField(placeholder: "0000", text: $registerVM.nameText)
.frame(maxWidth: .infinity,maxHeight: 48)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
.background {
RoundedRectangle(cornerRadius: 24)
.foregroundStyle(Color(.Normal.light))
}
}
.padding()
HStack(spacing: 0){
Text("연락처")
.font(.nps(size: 16))
.frame(width: 60, alignment: .leading)
Spacer(minLength: 1)
SimpleBtnView(vm: btnVM, id: addressBtnID)
.padding(EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20))
}
.padding()
// address
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.sheet(isPresented: $showWebView) {
WebView(isLoding: $showWebView)
.edgesIgnoringSafeArea(.all)
}
}
.onAppear {
@ -49,6 +158,12 @@ struct RegisterView: View {
topVM.setLeftBtn(Image(.Icon.left), size: CGPoint(x: 40, y: 40), action: leftAct)
topVM.setRightBtn(size: CGPoint(x: 40, y: 40), action: rightAct)
btnVM.setSize(for: addressBtnID, newWidth: 80, newHeight: 24)
btnVM.setText(for: addressBtnID, newText: "주소 입력", newFont: .nps(size: 16))
btnVM.setAction(for: addressBtnID) {
// self.appVM.isLoading.toggle()
self.showWebView.toggle()
}
}
}

View File

@ -9,7 +9,11 @@ import SwiftUI
struct SelectAcademyView: View {
@EnvironmentObject var appVM: AppViewModel
@StateObject var saVM = SelectAcademyViewModel()
@StateObject var saVM: SelectAcademyViewModel
init(_ appVM: AppViewModel) {
_saVM = StateObject(wrappedValue: SelectAcademyViewModel(appVM))
}
@State private var scrollOffset: CGPoint = .zero

View File

@ -10,7 +10,6 @@ import Combine
struct MainView: View {
@EnvironmentObject var appVM: AppViewModel
@EnvironmentObject var alertController: AlertController
@State var cancellables: Set<AnyCancellable> = []
// @Binding var naviState : NaviState

View File

@ -1,19 +0,0 @@
//
// AlertController.swift
// AcaMate
//
// Created by Sean Kim on 12/13/24.
//
import SwiftUI
import Combine
class AlertViewModel2: ObservableObject {
@Published var showAlert: Bool = false
var alertData: AlertData = .init(body: "")
let alertAction = CurrentValueSubject<String?, Never>(nil)
}

View File

@ -9,6 +9,8 @@ import SwiftUI
import Combine
class AppViewModel: ObservableObject {
// public static let shared = AppViewModel()
@Published var isLoading: Bool = false
@Published var showAlert: Bool = false
@Published var menuName: MenuName = .Home
@ -18,5 +20,10 @@ class AppViewModel: ObservableObject {
///
let alertAction = CurrentValueSubject<String?, Never>(nil)
var apiManager: APIManager = APIManager()
// private init() {
//
// }
//
}

View File

@ -6,9 +6,17 @@
//
import SwiftUI
final class ChatVM: ObservableObject {
@Published var vm: ChatViewModel?
}
class ChatViewModel: ObservableObject {
private let appVM: AppViewModel
@Published var messages: [ChatMesage] = []
init(_ appVM: AppViewModel) {
self.appVM = appVM
}
}

View File

@ -8,15 +8,15 @@
import SwiftUI
import Combine
class IntroViewModel: ObservableObject {
var appVM : AppViewModel
private let appVM: AppViewModel
private var cancellables = Set<AnyCancellable>()
// @Published var toggleLoading: Bool = false
// @Published var pathName: PathName = .NONE
@UserDefault(key: "header", defaultValue: "headerValue") var headerValue
init(appVM: AppViewModel) {
init(_ appVM: AppViewModel) {
self.appVM = appVM
}
@ -83,7 +83,7 @@ class IntroViewModel: ObservableObject {
decoding: APIResponse<Header>.self)
APIManager.shared.loadAPIData(request)
appVM.apiManager.loadAPIData(request)
.sink { completion in
switch completion {
case .failure(let error):
@ -133,7 +133,7 @@ class IntroViewModel: ObservableObject {
parameters: ["type":"I"],
decoding: APIResponse<VersionData>.self)
APIManager.shared.loadAPIData(request)
appVM.apiManager.loadAPIData(request)
.sink { completion in
switch completion {
case .failure(let error):

View File

@ -8,9 +8,9 @@
import SwiftUI
import Combine
class LoginViewModel: ObservableObject {
let appVM: AppViewModel
private let appVM: AppViewModel
private var cancellables = Set<AnyCancellable>()
// @Published var toggleLoading: Bool = false
@ -22,7 +22,8 @@ class LoginViewModel: ObservableObject {
var bidArray: [String] = []
init(appVM: AppViewModel) {
init(_ appVM: AppViewModel) {
self.appVM = appVM
}
@ -30,7 +31,7 @@ class LoginViewModel: ObservableObject {
appVM.isLoading = true
LoginController().login(type)
.flatMap{ snsId in
APIManager.shared.loadAPIData(APIRequest(path: "/api/v1/in/user/login",
self.appVM.apiManager.loadAPIData(APIRequest(path: "/api/v1/in/user/login",
headers: [API_HEADER : self.headerValue],
parameters: [
"acctype": "\(type == .Apple ? "ST00": "ST01")",

View File

@ -0,0 +1,31 @@
//
// RegisterViewModel.swift
// AcaMate
//
// Created by TAnine on 3/24/25.
//
import SwiftUI
import Combine
class RegisterViewModel: ObservableObject {
private let appVM: AppViewModel
private var cancellables = Set<AnyCancellable>()
init(_ appVM: AppViewModel) {
self.appVM = appVM
}
@State var selectDate: Date = {
let calendar = Calendar.current
return calendar.date(byAdding: .year, value: -12, to: Date()) ?? Date()
}()
@State var nameText: String = ""
@State var emailFrontText: String = ""
@State var emailTailText: String = ""
@State var phoneArray: [Int] = []
@State var addressText: String = ""
}

View File

@ -9,8 +9,13 @@ import SwiftUI
import Combine
class SelectAcademyViewModel: ObservableObject {
private var appVM: AppViewModel
private var cancellables: Set<AnyCancellable> = []
init(_ appVM: AppViewModel) {
self.appVM = appVM
}
@Published var academyCode: String = ""
@Published var academyList: [AcademyName] = []
@Published var selectNum: Int = -1
@ -23,7 +28,7 @@ class SelectAcademyViewModel: ObservableObject {
parameters: ["token": token, "refresh": refresh],
decoding: APIResponse<[AcademyName]>.self)
APIManager.shared.loadAPIData(request)
appVM.apiManager.loadAPIData(request)
.sink { completion in
switch completion {
case .failure(let error):

View File

@ -8,18 +8,18 @@
import Foundation
import Combine
import Alamofire
public class APIManager {
private var cancellables = Set<AnyCancellable>()
public static let shared = APIManager()
// public static let shared = APIManager()
@UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh
@UserDefault(key: "token", defaultValue: "accToken") var accToken
private init(cancellables: Set<AnyCancellable> = Set<AnyCancellable>()) {
self.cancellables = cancellables
}
// private init(cancellables: Set<AnyCancellable> = Set<AnyCancellable>()) {
// self.cancellables = cancellables
// }
public func loadAPIData<T: APIResponseProtocol>(_ request: APIRequest<T>) -> Future<T, Error> {
let encoding: ParameterEncoding = (request.method == .get) ? URLEncoding.default : JSONEncoding.default
@ -58,7 +58,7 @@ public class APIManager {
parameters: ["refresh": refresh],
decoding: APIResponse<Access>.self)
APIManager.shared.loadAPIData(request)
APIManager().loadAPIData(request)
.sink { completion in
switch completion {
case .failure(let error):
@ -105,7 +105,7 @@ public class APIManager {
self.accToken = (response as! Access).access
var updateRequest = request
updateRequest.parameters["token"] = self.accToken
return APIManager.shared.loadAPIData(updateRequest)
return APIManager().loadAPIData(updateRequest)
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()

View File

@ -29,7 +29,7 @@ struct AcaMateApp: App {
_ = AuthController.handleOpenUrl(url: url)
}
}
.environmentObject(self.appVM)
.environmentObject(appVM)
}
}
}