You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
PadelClub/PadelClub/Views/Player/Components/PlayerPopoverView.swift

269 lines
10 KiB

//
// PlayerPopoverView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 24/03/2024.
//
import SwiftUI
import PadelClubData
struct PlayerPopoverView: View {
enum PlayerCreationField {
case firstName, lastName, license, rank
}
@Environment(\.dismiss) var dismiss
@State private var displayWrongLicenceError: Bool = false
@State private var firstName: String = ""
@State private var lastName: String = ""
@State private var license: String = ""
@State private var rank: Int?
@State var sex: Int = 1
let requiredField: [PlayerCreationField]
let creationCompletionHandler: ((PlayerRegistration) -> Void)
@FocusState private var firstNameIsFocused: Bool
@FocusState private var lastNameIsFocused: Bool
@FocusState private var licenseIsFocused: Bool
@FocusState private var amountIsFocused: Bool
@State private var source: String?
init(source: String? = nil, sex: Int, requiredField: [PlayerCreationField] = [], creationCompletionHandler: @escaping (PlayerRegistration) -> Void) {
if let source {
let words = source.components(separatedBy: .whitespaces)
if words.isEmpty == false {
_firstName = State(wrappedValue: words.first?.capitalized ?? "")
if words.count > 1 {
_lastName = State(wrappedValue: words.last?.capitalized ?? "")
}
} else {
_firstName = State(wrappedValue: source)
}
_source = State(wrappedValue: source)
}
_sex = State(wrappedValue: sex)
_rank = State(wrappedValue: nil)
self.requiredField = requiredField
self.creationCompletionHandler = creationCompletionHandler
}
var body: some View {
NavigationStack {
List {
if let source {
Section {
Text(source).foregroundColor(.clear).padding(8)
.frame(maxWidth: .infinity)
.overlay(
TextEditor(text: .constant(source))
)
.frame(minHeight: 20.0)
} header: {
HStack {
Spacer()
Button(role: .cancel) {
self.source = nil
} label: {
Text("effacer le contenu du presse-papier")
.font(.caption)
}
.buttonStyle(.borderless)
}
}
.textCase(nil)
}
Section {
Picker(selection: $sex) {
Text("Homme").tag(1 as Int)
Text("Femme").tag(0 as Int)
} label: {
}
.labelsHidden()
.pickerStyle(.segmented)
HStack {
Text("Prénom").foregroundStyle(.secondary)
Spacer()
TextField("Prénom", text: $firstName)
.submitLabel(.next)
.autocorrectionDisabled()
.keyboardType(.alphabet)
.textInputAutocapitalization(.words)
.focused($firstNameIsFocused)
.onSubmit {
firstName = firstName.trimmedMultiline
lastNameIsFocused = true
}
.fixedSize()
}
HStack {
Text("Nom").foregroundStyle(.secondary)
Spacer()
TextField("Nom", text: $lastName)
.submitLabel(.next)
.autocorrectionDisabled()
.textInputAutocapitalization(.words)
.keyboardType(.alphabet)
.focused($lastNameIsFocused)
.onSubmit {
lastName = lastName.trimmedMultiline
licenseIsFocused = true
}
.fixedSize()
}
HStack {
Text("Licence").foregroundStyle(.secondary)
Spacer()
TextField("Licence", text: $license)
.focused($licenseIsFocused)
.textInputAutocapitalization(.never)
.keyboardType(.alphabet)
.submitLabel(.next)
.onSubmit {
license = license.trimmedMultiline
if license.isEmpty == false {
if license.isLicenseNumber {
amountIsFocused = true
} else {
displayWrongLicenceError = true
}
} else {
amountIsFocused = true
}
}
.fixedSize()
}
HStack {
Text("Rang").foregroundStyle(.secondary)
Spacer()
TextField("Non Classé" + (sex == 1 ? "" : "e"), value: $rank, format: .number)
.focused($amountIsFocused)
.textInputAutocapitalization(.never)
.keyboardType(.numberPad)
.submitLabel(.done)
.fixedSize()
}
} header: {
HStack {
Spacer()
Button(role: .cancel) {
let last = firstName
firstName = lastName
lastName = last
} label: {
Text("inverser nom & prénom")
.font(.caption)
}.buttonStyle(.borderless)
}
.textCase(nil)
}
.multilineTextAlignment(.trailing)
Section {
RowButtonView("Valider et ajouter un autre") {
createManualPlayer()
lastName = ""
firstName = ""
license = ""
rank = nil
firstNameIsFocused = true
}
.disabled(isPlayerValid() == false)
}
}
.onAppear {
firstNameIsFocused = true
}
.navigationTitle(sex == 1 ? "Nouveau joueur" : "Nouvelle joueuse")
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
ButtonValidateView {
createManualPlayer()
dismiss()
}
.disabled(isPlayerValid() == false)
}
ToolbarItem(placement: .cancellationAction) {
Button("Annuler", role : .cancel) {
dismiss()
}
}
if licenseIsFocused || amountIsFocused {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Confirmer") {
if licenseIsFocused {
license = license.trimmedMultiline
if requiredField.contains(.license) {
if license.isLicenseNumber {
amountIsFocused = true
} else {
displayWrongLicenceError = true
}
} else {
amountIsFocused = true
}
} else {
amountIsFocused = false
}
}
.buttonStyle(.borderedProminent)
}
}
}
.alert("Attention", isPresented: $displayWrongLicenceError) {
Button("OK") {
}
} message: {
Text("La licence n'est pas valide")
}
}
}
func isPlayerValid() -> Bool {
guard (lastName.isEmpty == false && requiredField.contains(.lastName)) || requiredField.contains(.lastName) == false else {
return false
}
guard (license.isEmpty == false && license.isLicenseNumber && requiredField.contains(.license)) || requiredField.contains(.license) == false else {
return false
}
guard (firstName.isEmpty == false && requiredField.contains(.firstName)) || requiredField.contains(.firstName) == false else {
return false
}
return true
}
func createManualPlayer() {
let playerRegistration = PlayerRegistration(
firstName: firstName.trimmedMultiline,
lastName: lastName.trimmedMultiline,
licenceId: license.trimmedMultiline.isEmpty ? nil : license,
rank: rank,
sex: PlayerSexType(rawValue: sex))
self.creationCompletionHandler(playerRegistration)
}
}
//#Preview {
// PlayerPopoverView(source: "Razmig Sarkissian", sex: 1) { player in
//
// }
//}