Aggiunge i18n IT/EN/FR/DE/ES, pagine pubbliche squadre e UX archivio.
Il selettore lingua funziona sul web e sulle app native; su Android la preferenza è persistita e applicata al riavvio. Incluse anche eliminazione replay a scope e campi pagina pubblica squadra. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -9,6 +9,8 @@ struct LoginScreen: View {
|
||||
@State private var error: String?
|
||||
@State private var loading = false
|
||||
@State private var passwordVisible = false
|
||||
@State private var showLanguagePicker = false
|
||||
@State private var languageTick = 0
|
||||
|
||||
var body: some View {
|
||||
MatchScreenScaffold {
|
||||
@@ -16,17 +18,17 @@ struct LoginScreen: View {
|
||||
VStack(spacing: 0) {
|
||||
MatchLiveWordmark(showSlogan: true)
|
||||
.padding(.top, 32)
|
||||
Text("ACCEDI")
|
||||
Button(L10n.t("language.label")) {
|
||||
showLanguagePicker = true
|
||||
}
|
||||
.foregroundStyle(MatchColors.textSecondary)
|
||||
.padding(.top, 16)
|
||||
Text(L10n.t("login.submit").uppercased())
|
||||
.font(MatchTypography.headlineMedium)
|
||||
.padding(.top, 48)
|
||||
Text("Gestisci le dirette della tua squadra")
|
||||
.font(MatchTypography.bodyMedium)
|
||||
.foregroundStyle(MatchColors.textSecondary)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.top, 8)
|
||||
.padding(.top, 32)
|
||||
VStack(spacing: 16) {
|
||||
MatchTextField(title: "Email", text: $email, placeholder: "coach@squadra.it", keyboard: .emailAddress)
|
||||
MatchSecureField(title: "Password", text: $password, visible: $passwordVisible)
|
||||
MatchTextField(title: L10n.t("login.email"), text: $email, placeholder: "coach@squadra.it", keyboard: .emailAddress)
|
||||
MatchSecureField(title: L10n.t("login.password"), text: $password, visible: $passwordVisible)
|
||||
}
|
||||
.padding(.top, 32)
|
||||
if let error {
|
||||
@@ -36,7 +38,7 @@ struct LoginScreen: View {
|
||||
.padding(.top, 12)
|
||||
}
|
||||
MatchPrimaryButton(
|
||||
label: "ACCEDI",
|
||||
label: L10n.t("login.submit").uppercased(),
|
||||
action: submitLogin,
|
||||
enabled: !email.isEmpty && !password.isEmpty,
|
||||
loading: loading
|
||||
@@ -47,6 +49,13 @@ struct LoginScreen: View {
|
||||
.padding(.bottom, 32)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showLanguagePicker) {
|
||||
LanguagePickerView()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .appLanguageDidChange)) { _ in
|
||||
languageTick += 1
|
||||
}
|
||||
.id(languageTick)
|
||||
}
|
||||
|
||||
private func submitLogin() {
|
||||
@@ -59,12 +68,12 @@ struct LoginScreen: View {
|
||||
onLoggedIn()
|
||||
} catch {
|
||||
if let apiError = error as? APIError, case .unauthorized = apiError {
|
||||
self.error = "Email o password non corretti"
|
||||
self.error = L10n.t("login.error.credentials")
|
||||
} else if let message = UserFacingError.message(for: error),
|
||||
message.localizedCaseInsensitiveContains("timeout") {
|
||||
self.error = "Server non raggiungibile. Verifica la connessione."
|
||||
self.error = L10n.t("login.error.unreachable")
|
||||
} else {
|
||||
self.error = UserFacingError.message(for: error) ?? "Accesso non riuscito"
|
||||
self.error = UserFacingError.message(for: error) ?? L10n.t("login.error.generic")
|
||||
}
|
||||
}
|
||||
loading = false
|
||||
|
||||
@@ -20,6 +20,8 @@ struct MatchesScreen: View {
|
||||
@State private var resumeMatch: Match?
|
||||
@State private var deleteMatch: Match?
|
||||
@State private var snackbar: String?
|
||||
@State private var showLanguagePicker = false
|
||||
@State private var languageTick = 0
|
||||
|
||||
var body: some View {
|
||||
MatchScreenScaffold(
|
||||
@@ -27,7 +29,14 @@ struct MatchesScreen: View {
|
||||
HStack {
|
||||
MatchLiveWordmark(compact: true)
|
||||
Spacer()
|
||||
Button("Esci") {
|
||||
Button {
|
||||
showLanguagePicker = true
|
||||
} label: {
|
||||
Image(systemName: "globe")
|
||||
.foregroundStyle(MatchColors.textSecondary)
|
||||
}
|
||||
.accessibilityLabel(L10n.t("language.label"))
|
||||
Button(L10n.t("action.logout")) {
|
||||
Task {
|
||||
await container.authRepository.logout()
|
||||
onLogout()
|
||||
@@ -177,6 +186,13 @@ struct MatchesScreen: View {
|
||||
showTeamPicker = false
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showLanguagePicker) {
|
||||
LanguagePickerView()
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .appLanguageDidChange)) { _ in
|
||||
languageTick += 1
|
||||
}
|
||||
.id(languageTick)
|
||||
.overlay {
|
||||
if actionLoading {
|
||||
Color.black.opacity(0.35)
|
||||
|
||||
Reference in New Issue
Block a user