Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Sources/App/MainTabView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// TabView.swift
// megabox
//
// Created by 문인성 on 10/8/25.
//

import SwiftUI

struct MainTabView: View {
var body: some View {
TabView {
Tab("홈" , systemImage: "house.fill") {
Home()
}

Tab("바로 예매" , systemImage: "play.laptopcomputer") {
LoginView(viewModel: LoginViewModel())
}

Tab("모바일 오더" , systemImage: "popcorn") {
MobileOrderView()
}

Tab("마이 페이지" , systemImage: "person") {
UserInformation()

}
}
}
}

#Preview {
MainTabView()
}
28 changes: 28 additions & 0 deletions Sources/App/MegaboxApp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import SwiftUI

@main
struct YourApp: App {

@StateObject private var viewModel = LoginViewModel()

@State private var isSplashFinished: Bool = false

var body: some Scene {
WindowGroup {

if !isSplashFinished {
SplashView(isSplashFinished: $isSplashFinished)

} else {

if viewModel.isLoggedIn {
MainTabView()
.environmentObject(viewModel)
} else {
// (checkAutoLogin()이 실패했다면)
LoginView(viewModel: viewModel)
}
}
}
}
}
14 changes: 14 additions & 0 deletions Sources/Authentication/LoginModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// LoginModel.swift
// megabox
//
// Created by 문인성 on 9/25/25.
//

import Foundation

struct LoginModel {
var id: String = ""
var pwd: String = ""
}

99 changes: 99 additions & 0 deletions Sources/Authentication/LoginView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// LoginView.swift

import SwiftUI

struct LoginView: View {

@StateObject private var viewModel: LoginViewModel

init(viewModel: LoginViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
}

@State private var showAlert: Bool = false

var body: some View {
VStack {
HStack {
Text("로그인")
.font(.semiBold24)
.padding(.top, 44)
}

Spacer()

VStack {
TextField("아이디", text: $viewModel.loginInfo.id)
.padding(.horizontal, 16)
Divider()
.padding(.horizontal, 16)

SecureField("비밀번호", text: $viewModel.loginInfo.pwd)
.padding(.horizontal, 16)
Divider()
.padding(.horizontal, 16)
.padding(.bottom, 74.98)


Button(action: {

viewModel.handleLogin()

if !viewModel.isLoggedIn {
showAlert = true
}

}) {
Text("로그인")
.font(.headline)
.fontWeight(.bold)
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.padding(.vertical, 9)
.background(Color.purple) // Color("purple03")
.cornerRadius(10)
}
.padding(.horizontal, 16.5)
.padding(.bottom, 17)

Text("회원가입")
.font(.medium13)
.foregroundStyle(Color.gray) // Color("gray04")
}

}

.alert("로그인 실패", isPresented: $showAlert) {
Button("확인", role: .cancel) {}
} message: {
Text("아이디 또는 비밀번호를 확인해주세요.")
}

HStack {
Image("naverLoginBtn")
Spacer()
Image("kakaoLoginBtn")
Spacer()
Image("appleLoginBtn")
}
.frame(maxWidth: .infinity)
.padding(.top, 35)
.padding(.horizontal, 87)
.padding(.bottom, 39)

HStack {
Image("umc")
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
}

Spacer()

}
}

#Preview {
LoginView(viewModel: LoginViewModel())
}
66 changes: 66 additions & 0 deletions Sources/Authentication/LoginViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// LoginViewModel.swift
// (이 코드로 파일 전체를 덮어쓰세요)

import Foundation

class LoginViewModel: ObservableObject {

@Published var loginInfo = LoginModel()
@Published var isLoggedIn: Bool = false
@Published var userName: String = "" // 마이페이지 표시용


private let idAccount = "userID"
private let pwdAccount = "userPassword"

init() {
checkAutoLogin()
}

func checkAutoLogin() {
guard let savedId = KeychainHelper.read(account: idAccount),
let savedPwd = KeychainHelper.read(account: pwdAccount) else {
print("No credentials found in Keychain.")
return
}

print("Auto login successful.")
self.userName = savedId // 마이페이지용 이름 설정 (체크리스트 3번)
self.isLoggedIn = true // 로그인 상태를 true로 변경
}

func handleLogin() {
let correctId = "swift"
let correctPwd = "1234"

if loginInfo.id == correctId && loginInfo.pwd == correctPwd {
let idSaved = KeychainHelper.save(string: loginInfo.id, account: idAccount)
let pwdSaved = KeychainHelper.save(string: loginInfo.pwd, account: pwdAccount)

if idSaved && pwdSaved {
print("Credentials saved to Keychain.")
self.userName = loginInfo.id
self.isLoggedIn = true
} else {
print("Failed to save credentials to Keychain.")
}

} else {
print("Login failed: Incorrect ID or PWD.")
}
}

func handleLogout() {
let idDeleted = KeychainHelper.delete(account: idAccount)
let pwdDeleted = KeychainHelper.delete(account: pwdAccount)

if idDeleted && pwdDeleted {
print("Credentials deleted from Keychain.")
} else {
print("Could not delete credentials from Keychain.")
}

self.isLoggedIn = false
self.userName = "" // 저장된 사용자 이름도 지웁니다.
}
}
56 changes: 56 additions & 0 deletions Sources/Authentication/SplashView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// SplashView.swift
// megabox
//
// Created by 문인성 on 9/24/25.
//

import SwiftUI

struct SplashView: View {

@Binding var isSplashFinished: Bool

var body: some View {

ZStack {
Color(.white)
Image("megaboxLogo")
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity)
.padding(.horizontal, 95)
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
withAnimation {
self.isSplashFinished = true
}
}
}
}
}

struct PreviewWrapper2: View {
@State private var test = ""

var body: some View {
TextEditor(text: $test)
.frame(height: 100)
.border(Color.gray, width: 1)
}
}

struct PreviewWrapper_previews2: PreviewProvider {
static let devices = [ "iPhone 16 Pro Max",
"iPhone 11"]

static var previews: some View {
ForEach(devices, id: \.self) { device in

SplashView(isSplashFinished: .constant(false))
.previewDevice(PreviewDevice(rawValue: device))
.previewDisplayName(device)
}
}
}
Loading