154 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						||
//  LoginView.swift
 | 
						||
//  VolnahubApp
 | 
						||
//
 | 
						||
//  Created by cheykrym on 09/06/2025.
 | 
						||
//
 | 
						||
 | 
						||
import SwiftUI
 | 
						||
 | 
						||
struct LoginView: View {
 | 
						||
    @ObservedObject var viewModel: LoginViewModel
 | 
						||
    @AppStorage("isDarkMode") private var isDarkMode: Bool = true
 | 
						||
    
 | 
						||
    @State private var isShowingRegistration = false
 | 
						||
 | 
						||
    private var isUsernameValid: Bool {
 | 
						||
        let pattern = "^[A-Za-z0-9_]{3,32}$"
 | 
						||
        return viewModel.username.range(of: pattern, options: .regularExpression) != nil
 | 
						||
    }
 | 
						||
 | 
						||
    private var isPasswordValid: Bool {
 | 
						||
        return viewModel.password.count >= 6 && viewModel.password.count <= 32
 | 
						||
    }
 | 
						||
    
 | 
						||
    var body: some View {
 | 
						||
 | 
						||
        VStack {
 | 
						||
            HStack {
 | 
						||
 | 
						||
                Button(action: openLanguageSettings) {
 | 
						||
                    Text("🌍 " + NSLocalizedString("LoginView_change_language", comment: ""))
 | 
						||
                        .padding()
 | 
						||
                }
 | 
						||
                Spacer()
 | 
						||
                Button(action: toggleTheme) {
 | 
						||
                    Image(systemName: isDarkMode ? "moon.fill" : "sun.max.fill")
 | 
						||
                        .padding()
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            Spacer()
 | 
						||
 | 
						||
            
 | 
						||
//            Text(NSLocalizedString("LoginView_title", comment: ""))
 | 
						||
//                .font(.largeTitle)
 | 
						||
//                .bold()
 | 
						||
 | 
						||
            TextField(NSLocalizedString("LoginView_login", comment: ""), text: $viewModel.username)
 | 
						||
                .padding()
 | 
						||
                .background(Color(.secondarySystemBackground))
 | 
						||
                .cornerRadius(8)
 | 
						||
                .autocapitalization(.none)
 | 
						||
                .disableAutocorrection(true)
 | 
						||
                .onChange(of: viewModel.username) { newValue in
 | 
						||
                    if newValue.count > 32 {
 | 
						||
                        viewModel.username = String(newValue.prefix(32))
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
            // Показываем ошибку для логина
 | 
						||
            if !isUsernameValid && !viewModel.username.isEmpty {
 | 
						||
                Text(NSLocalizedString("LoginView_error_username_invalid", comment: "Неверный логин"))
 | 
						||
                    .foregroundColor(.red)
 | 
						||
                    .font(.caption)
 | 
						||
            }
 | 
						||
 | 
						||
            // Показываем поле пароля (даже если оно невалидное) только если логин корректен
 | 
						||
            if isUsernameValid {
 | 
						||
                SecureField(NSLocalizedString("LoginView_password", comment: ""), text: $viewModel.password)
 | 
						||
                    .padding()
 | 
						||
                    .background(Color(.secondarySystemBackground))
 | 
						||
                    .cornerRadius(8)
 | 
						||
                    .autocapitalization(.none)
 | 
						||
                    .onChange(of: viewModel.password) { newValue in
 | 
						||
                        if newValue.count > 32 {
 | 
						||
                            viewModel.password = String(newValue.prefix(32))
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
 | 
						||
                // Показываем ошибку для пароля
 | 
						||
                if !isPasswordValid && !viewModel.password.isEmpty {
 | 
						||
                    Text(NSLocalizedString("LoginView_error_password_invalid", comment: "Неверный пароль"))
 | 
						||
                        .foregroundColor(.red)
 | 
						||
                        .font(.caption)
 | 
						||
                }
 | 
						||
            }
 | 
						||
            
 | 
						||
            if isUsernameValid && isPasswordValid {
 | 
						||
                Button(action: {
 | 
						||
                    viewModel.login()
 | 
						||
                }) {
 | 
						||
                    if viewModel.isLoading {
 | 
						||
                        ProgressView()
 | 
						||
                            .progressViewStyle(CircularProgressViewStyle())
 | 
						||
                            .padding()
 | 
						||
                            .frame(maxWidth: .infinity)
 | 
						||
                            .background(Color.gray.opacity(0.6))
 | 
						||
                            .cornerRadius(8)
 | 
						||
                    } else {
 | 
						||
                        Text(NSLocalizedString("LoginView_button_login", comment: ""))
 | 
						||
                            .foregroundColor(.white)
 | 
						||
                            .padding()
 | 
						||
                            .frame(maxWidth: .infinity)
 | 
						||
                            .background(Color.blue)
 | 
						||
                            .cornerRadius(8)
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                .disabled(viewModel.isLoading)
 | 
						||
            }
 | 
						||
 | 
						||
            Spacer()
 | 
						||
            
 | 
						||
            // Кнопка регистрации
 | 
						||
            Button(action: {
 | 
						||
                isShowingRegistration = true
 | 
						||
            }) {
 | 
						||
                Text(NSLocalizedString("LoginView_button_register", comment: "Регистрация"))
 | 
						||
                    .foregroundColor(.blue)
 | 
						||
            }
 | 
						||
            .padding(.top, 10)
 | 
						||
            .sheet(isPresented: $isShowingRegistration) {
 | 
						||
                RegistrationView()
 | 
						||
            }
 | 
						||
            
 | 
						||
        }
 | 
						||
        .padding()
 | 
						||
        .alert(isPresented: $viewModel.showError) {
 | 
						||
            Alert(
 | 
						||
                title: Text(NSLocalizedString("LoginView_error", comment: "")),
 | 
						||
                message: Text(viewModel.errorMessage),
 | 
						||
                dismissButton: .default(Text("ОК"))
 | 
						||
            )
 | 
						||
        }
 | 
						||
    }
 | 
						||
    
 | 
						||
    private func toggleTheme() {
 | 
						||
        isDarkMode.toggle()
 | 
						||
    }
 | 
						||
    
 | 
						||
    private func openLanguageSettings() {
 | 
						||
        guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
 | 
						||
        UIApplication.shared.open(url)
 | 
						||
    }
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
struct LoginView_Previews: PreviewProvider {
 | 
						||
    static var previews: some View {
 | 
						||
        let viewModel = LoginViewModel()
 | 
						||
        viewModel.isLoading = false // чтобы убрать спиннер
 | 
						||
        return LoginView(viewModel: viewModel)
 | 
						||
    }
 | 
						||
}
 |