130 lines
6.1 KiB
Swift
130 lines
6.1 KiB
Swift
import SwiftUI
|
|
|
|
struct AuthView: View {
|
|
@EnvironmentObject private var model: AppModel
|
|
@State private var registering = false
|
|
@State private var login = ""
|
|
@State private var password = ""
|
|
@State private var form = RegistrationForm()
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: 14) {
|
|
HStack {
|
|
Image("Logo")
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(height: 58)
|
|
Spacer()
|
|
LanguageButton()
|
|
}
|
|
.padding(.bottom, 18)
|
|
|
|
if registering { registrationForm }
|
|
else { loginForm }
|
|
}
|
|
.padding(22)
|
|
}
|
|
.scrollDismissesKeyboard(.interactively)
|
|
.background(KTheme.background)
|
|
}
|
|
|
|
private var loginForm: some View {
|
|
VStack(alignment: .leading, spacing: 14) {
|
|
Text(model.text("Zaloguj się", "Sign in")).font(.largeTitle.bold())
|
|
Text(model.text("Twoja karta i punkty będą dostępne po zalogowaniu.", "Your card and points will be available after signing in."))
|
|
.foregroundStyle(.secondary)
|
|
KasztelanField(title: model.text("E-mail lub login", "Email or username"), text: $login, keyboard: .emailAddress, contentType: .username)
|
|
KasztelanField(title: model.text("Hasło", "Password"), text: $password, secure: true, contentType: .password)
|
|
Button(model.text("Zaloguj", "Sign in")) {
|
|
guard !login.trimmingCharacters(in: .whitespaces).isEmpty, !password.isEmpty else {
|
|
model.errorMessage = model.text("Wpisz login i hasło.", "Enter your username and password.")
|
|
return
|
|
}
|
|
Task { await model.login(login: login, password: password) }
|
|
}
|
|
.buttonStyle(PrimaryButtonStyle())
|
|
Link(destination: URL(string: "https://kasztelan.co.uk/forgot/")!) {
|
|
HStack(spacing: 8) {
|
|
Image(systemName: "key.fill")
|
|
Text(model.text("Nie pamiętasz hasła?", "Forgot your password?"))
|
|
}
|
|
.font(.subheadline.bold())
|
|
.foregroundStyle(KTheme.orange)
|
|
.frame(maxWidth: .infinity, minHeight: 46)
|
|
}
|
|
.accessibilityLabel(model.text("Otwórz resetowanie hasła", "Open password reset"))
|
|
Button(model.text("Załóż konto", "Create account")) { registering = true }
|
|
.frame(maxWidth: .infinity, minHeight: 50)
|
|
.background(KTheme.panel)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16))
|
|
}
|
|
}
|
|
|
|
private var registrationForm: some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
Text(model.text("Załóż konto", "Create account")).font(.largeTitle.bold())
|
|
KasztelanField(title: model.text("Imię", "First name"), text: $form.firstName, contentType: .givenName)
|
|
KasztelanField(title: model.text("Nazwisko", "Last name"), text: $form.lastName, contentType: .familyName)
|
|
KasztelanField(title: "E-mail", text: $form.email, keyboard: .emailAddress, contentType: .emailAddress)
|
|
KasztelanField(title: model.text("Hasło", "Password"), text: $form.password, secure: true, contentType: .newPassword)
|
|
KasztelanField(title: model.text("Telefon UK lub PL", "UK or Polish phone number"), text: $form.mobile, keyboard: .phonePad, contentType: .telephoneNumber)
|
|
KasztelanField(title: model.text("Kod pocztowy UK", "UK postcode"), text: $form.postcode, contentType: .postalCode)
|
|
KasztelanField(title: model.text("Data urodzenia: RRRR-MM-DD", "Date of birth: YYYY-MM-DD"), text: dateBinding, keyboard: .numberPad)
|
|
KasztelanField(title: model.text("Numer karty (opcjonalnie)", "Card number (optional)"), text: $form.cardNumber, keyboard: .numberPad)
|
|
Toggle(model.text("Akceptuję regulamin", "I accept the terms"), isOn: $form.acceptsTerms)
|
|
.tint(KTheme.orange)
|
|
HStack(spacing: 16) {
|
|
Link(model.text("Regulamin", "Terms"), destination: URL(string: "https://kasztelan.co.uk/regulamin/")!)
|
|
Link(model.text("Polityka prywatności", "Privacy policy"), destination: URL(string: "https://kasztelan.co.uk/privacy-policy/")!)
|
|
}
|
|
.font(.subheadline.bold())
|
|
.foregroundStyle(KTheme.orange)
|
|
Button(model.text("Utwórz konto", "Create account")) {
|
|
Task { await model.register(form) }
|
|
}
|
|
.buttonStyle(PrimaryButtonStyle())
|
|
Button(model.text("Mam już konto", "I already have an account")) { registering = false }
|
|
.frame(maxWidth: .infinity, minHeight: 50)
|
|
.background(KTheme.panel)
|
|
.clipShape(RoundedRectangle(cornerRadius: 16))
|
|
}
|
|
}
|
|
|
|
private var dateBinding: Binding<String> {
|
|
Binding(
|
|
get: { form.dob },
|
|
set: { form.dob = Self.formatDateInput($0) }
|
|
)
|
|
}
|
|
|
|
static func formatDateInput(_ input: String) -> String {
|
|
let digits = String(input.filter(\.isNumber).prefix(8))
|
|
var result = ""
|
|
for (index, character) in digits.enumerated() {
|
|
if index == 4 || index == 6 { result.append("-") }
|
|
result.append(character)
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
struct LanguageButton: View {
|
|
@EnvironmentObject private var model: AppModel
|
|
|
|
var body: some View {
|
|
Button {
|
|
model.language = model.language == .pl ? .en : .pl
|
|
} label: {
|
|
Text(model.language == .pl ? "EN" : "PL")
|
|
.font(.subheadline.bold())
|
|
.foregroundStyle(KTheme.orange)
|
|
.frame(width: 44, height: 44, alignment: .center)
|
|
.background(KTheme.panel, in: Circle())
|
|
.contentShape(Circle())
|
|
}
|
|
.buttonStyle(.plain)
|
|
.accessibilityLabel(model.text("Zmień język na angielski", "Change language to Polish"))
|
|
}
|
|
}
|