fix stuff on manual player creation

multistore
Razmig Sarkissian 1 year ago
parent 2aad3da572
commit 93515db50a
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 22
      PadelClub/Data/Tournament.swift
  3. 2
      PadelClub/Utils/ContactManager.swift
  4. 5
      PadelClub/Views/GroupStage/GroupStageSettingsView.swift
  5. 13
      PadelClub/Views/Player/Components/PlayerPopoverView.swift
  6. 3
      PadelClub/Views/Player/PlayerDetailView.swift
  7. 6
      PadelClub/Views/Round/RoundSettingsView.swift
  8. 17
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  9. 5
      PadelClubTests/ServerDataTests.swift

@ -1919,7 +1919,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20; CURRENT_PROJECT_VERSION = 21;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6; DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -1957,7 +1957,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20; CURRENT_PROJECT_VERSION = 21;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6; DEVELOPMENT_TEAM = BQ3Y44M3Q6;

@ -48,8 +48,6 @@ class Tournament : ModelObject, Storable {
var publishSummons: Bool = false var publishSummons: Bool = false
var publishGroupStages: Bool = false var publishGroupStages: Bool = false
var publishBrackets: Bool = false var publishBrackets: Bool = false
//local
var shouldVerifyGroupStage: Bool = false var shouldVerifyGroupStage: Bool = false
var shouldVerifyBracket: Bool = false var shouldVerifyBracket: Bool = false
@ -94,9 +92,11 @@ class Tournament : ModelObject, Storable {
case _publishSummons = "publishSummons" case _publishSummons = "publishSummons"
case _publishGroupStages = "publishGroupStages" case _publishGroupStages = "publishGroupStages"
case _publishBrackets = "publishBrackets" case _publishBrackets = "publishBrackets"
case _shouldVerifyGroupStage = "shouldVerifyGroupStage"
case _shouldVerifyBracket = "shouldVerifyBracket"
} }
internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false) { internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishTeams: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false, shouldVerifyBracket: Bool = false, shouldVerifyGroupStage: Bool = false) {
self.event = event self.event = event
self.name = name self.name = name
self.startDate = startDate self.startDate = startDate
@ -128,6 +128,8 @@ class Tournament : ModelObject, Storable {
self.publishSummons = publishSummons self.publishSummons = publishSummons
self.publishBrackets = publishBrackets self.publishBrackets = publishBrackets
self.publishGroupStages = publishGroupStages self.publishGroupStages = publishGroupStages
self.shouldVerifyBracket = shouldVerifyBracket
self.shouldVerifyGroupStage = shouldVerifyGroupStage
} }
required init(from decoder: Decoder) throws { required init(from decoder: Decoder) throws {
@ -166,7 +168,8 @@ class Tournament : ModelObject, Storable {
publishSummons = try container.decodeIfPresent(Bool.self, forKey: ._publishSummons) ?? false publishSummons = try container.decodeIfPresent(Bool.self, forKey: ._publishSummons) ?? false
publishGroupStages = try container.decodeIfPresent(Bool.self, forKey: ._publishGroupStages) ?? false publishGroupStages = try container.decodeIfPresent(Bool.self, forKey: ._publishGroupStages) ?? false
publishBrackets = try container.decodeIfPresent(Bool.self, forKey: ._publishBrackets) ?? false publishBrackets = try container.decodeIfPresent(Bool.self, forKey: ._publishBrackets) ?? false
shouldVerifyBracket = try container.decodeIfPresent(Bool.self, forKey: ._shouldVerifyBracket) ?? false
shouldVerifyGroupStage = try container.decodeIfPresent(Bool.self, forKey: ._shouldVerifyGroupStage) ?? false
} }
fileprivate static let _numberFormatter: NumberFormatter = NumberFormatter() fileprivate static let _numberFormatter: NumberFormatter = NumberFormatter()
@ -276,6 +279,8 @@ class Tournament : ModelObject, Storable {
try container.encode(publishSummons, forKey: ._publishSummons) try container.encode(publishSummons, forKey: ._publishSummons)
try container.encode(publishBrackets, forKey: ._publishBrackets) try container.encode(publishBrackets, forKey: ._publishBrackets)
try container.encode(publishGroupStages, forKey: ._publishGroupStages) try container.encode(publishGroupStages, forKey: ._publishGroupStages)
try container.encode(shouldVerifyBracket, forKey: ._shouldVerifyBracket)
try container.encode(shouldVerifyGroupStage, forKey: ._shouldVerifyGroupStage)
} }
fileprivate func _encodePayment(container: inout KeyedEncodingContainer<CodingKeys>) throws { fileprivate func _encodePayment(container: inout KeyedEncodingContainer<CodingKeys>) throws {
@ -1152,6 +1157,15 @@ class Tournament : ModelObject, Storable {
return TournamentStatus(label: label, completion: completionLabel) return TournamentStatus(label: label, completion: completionLabel)
} }
func confirmedSummonStatus() -> TournamentStatus {
let selectedSortedTeams = selectedSortedTeams()
let called = selectedSortedTeams.filter { $0.confirmationDate != nil }
let label = called.count.formatted() + " / " + selectedSortedTeams.count.formatted() + " confirmées"
let completion = (Double(called.count) / Double(selectedSortedTeams.count))
let completionLabel = completion.isNaN ? "" : completion.formatted(.percent.precision(.fractionLength(0)))
return TournamentStatus(label: label, completion: completionLabel)
}
func bracketStatus() -> String { func bracketStatus() -> String {
let availableSeeds = availableSeeds() let availableSeeds = availableSeeds()
if availableSeeds.isEmpty == false { if availableSeeds.isEmpty == false {

@ -80,7 +80,7 @@ extension ContactType {
[entryFeeMessage, message].compacted().map { $0.trimmed }.joined(separator: "\n\n") [entryFeeMessage, message].compacted().map { $0.trimmed }.joined(separator: "\n\n")
} }
var intro = reSummon ? "Suite à des forfaits, vous êtes finalement" : "Vous êtes" let intro = reSummon ? "Suite à des forfaits, vous êtes finalement" : "Vous êtes"
if let tournament { if let tournament {
return "Bonjour,\n\n\(intro) \(localizedCalled) pour jouer en \(roundLabel.lowercased()) du \(tournament.tournamentTitle(.short)) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(signature)" return "Bonjour,\n\n\(intro) \(localizedCalled) pour jouer en \(roundLabel.lowercased()) du \(tournament.tournamentTitle(.short)) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(signature)"

@ -32,6 +32,11 @@ struct GroupStageSettingsView: View {
Section { Section {
RowButtonView("Valider les poules", role: .destructive) { RowButtonView("Valider les poules", role: .destructive) {
tournament.shouldVerifyGroupStage = false tournament.shouldVerifyGroupStage = false
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)
}
} }
} footer: { } footer: {
Text("Suite à changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de vos poules et valider que tout est ok.") Text("Suite à changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de vos poules et valider que tout est ok.")

@ -32,7 +32,6 @@ struct PlayerPopoverView: View {
@State private var source: String? @State private var source: String?
init(source: String?, sex: Int, requiredField: [PlayerCreationField] = [.firstName, .lastName], creationCompletionHandler: @escaping (PlayerRegistration) -> Void) { init(source: String?, sex: Int, requiredField: [PlayerCreationField] = [.firstName, .lastName], creationCompletionHandler: @escaping (PlayerRegistration) -> Void) {
let source = source
if let source { if let source {
let words = source.components(separatedBy: .whitespaces) let words = source.components(separatedBy: .whitespaces)
if words.isEmpty == false { if words.isEmpty == false {
@ -44,6 +43,8 @@ struct PlayerPopoverView: View {
} else { } else {
_firstName = State(wrappedValue: source) _firstName = State(wrappedValue: source)
} }
_source = State(wrappedValue: source)
} }
_sex = State(wrappedValue: sex) _sex = State(wrappedValue: sex)
@ -51,7 +52,6 @@ struct PlayerPopoverView: View {
self.requiredField = requiredField self.requiredField = requiredField
self.creationCompletionHandler = creationCompletionHandler self.creationCompletionHandler = creationCompletionHandler
_source = State(wrappedValue: source)
} }
var body: some View { var body: some View {
@ -94,6 +94,7 @@ struct PlayerPopoverView: View {
Spacer() Spacer()
TextField("Prénom", text: $firstName) TextField("Prénom", text: $firstName)
.submitLabel(.next) .submitLabel(.next)
.autocorrectionDisabled()
.keyboardType(.alphabet) .keyboardType(.alphabet)
.textInputAutocapitalization(.words) .textInputAutocapitalization(.words)
.focused($firstNameIsFocused) .focused($firstNameIsFocused)
@ -108,6 +109,7 @@ struct PlayerPopoverView: View {
Spacer() Spacer()
TextField("Nom", text: $lastName) TextField("Nom", text: $lastName)
.submitLabel(.next) .submitLabel(.next)
.autocorrectionDisabled()
.textInputAutocapitalization(.words) .textInputAutocapitalization(.words)
.keyboardType(.alphabet) .keyboardType(.alphabet)
.focused($lastNameIsFocused) .focused($lastNameIsFocused)
@ -180,7 +182,6 @@ struct PlayerPopoverView: View {
.onAppear { .onAppear {
firstNameIsFocused = true firstNameIsFocused = true
} }
.autocorrectionDisabled()
.navigationTitle(sex == 1 ? "Nouveau joueur" : "Nouvelle joueuse") .navigationTitle(sex == 1 ? "Nouveau joueur" : "Nouvelle joueuse")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar)
@ -199,8 +200,10 @@ struct PlayerPopoverView: View {
} }
} }
if amountIsFocused || licenseIsFocused { if licenseIsFocused || amountIsFocused {
ToolbarItem(placement: .keyboard) { ToolbarItem(placement: .keyboard) {
HStack {
Spacer()
Button("Confirmer") { Button("Confirmer") {
if licenseIsFocused { if licenseIsFocused {
license = license.trimmed license = license.trimmed
@ -217,6 +220,8 @@ struct PlayerPopoverView: View {
amountIsFocused = false amountIsFocused = false
} }
} }
.buttonStyle(.bordered)
}
} }
} }
} }

@ -46,6 +46,9 @@ struct PlayerDetailView: View {
.focused($textFieldIsFocus) .focused($textFieldIsFocus)
} label: { } label: {
Text("Rang") Text("Rang")
if player.rank == nil {
Text("Classement calculé : " + player.computedRank.formatted())
}
} }
} header: { } header: {
Text("Classement actuel") Text("Classement actuel")

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct RoundSettingsView: View { struct RoundSettingsView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@ -18,6 +19,11 @@ struct RoundSettingsView: View {
Section { Section {
RowButtonView("Valider le tableau", role: .destructive) { RowButtonView("Valider le tableau", role: .destructive) {
tournament.shouldVerifyBracket = false tournament.shouldVerifyBracket = false
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)
}
} }
} footer: { } footer: {
Text("Suite à changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de votre tableau et valider que tout est ok.") Text("Suite à changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de votre tableau et valider que tout est ok.")

@ -120,18 +120,22 @@ struct InscriptionManagerView: View {
} }
} }
.onAppear { .onAppear {
self.presentationCount += 1
if self.teamsHash == nil { if self.teamsHash == nil {
self.teamsHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id }) self.teamsHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id })
} }
} }
.onDisappear { .onDisappear {
self.presentationCount -= 1
if self.presentationCount == 0 {
let newHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id }) let newHash = _simpleHash(ids: tournament.selectedSortedTeams().map { $0.id })
if let teamsHash { if let teamsHash, newHash != teamsHash {
self.tournament.shouldVerifyBracket = newHash != teamsHash self.teamsHash = newHash
self.tournament.shouldVerifyGroupStage = newHash != teamsHash if self.tournament.shouldVerifyBracket == false || self.tournament.shouldVerifyGroupStage == false {
self.tournament.shouldVerifyBracket = true
self.tournament.shouldVerifyGroupStage = true
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)
}
} }
} }
} }
@ -161,6 +165,7 @@ struct InscriptionManagerView: View {
} }
.sheet(isPresented: $presentPlayerCreation) { .sheet(isPresented: $presentPlayerCreation) {
PlayerPopoverView(source: _searchSource(), sex: _addPlayerSex()) { p in PlayerPopoverView(source: _searchSource(), sex: _addPlayerSex()) { p in
p.setComputedRank(in: tournament)
createdPlayers.insert(p) createdPlayers.insert(p)
createdPlayerIds.insert(p.id) createdPlayerIds.insert(p.id)
} }

@ -96,7 +96,7 @@ final class ServerDataTests: XCTestCase {
return return
} }
let tournament = Tournament(event: eventId, name: "RG Homme", startDate: Date(), endDate: nil, creationDate: Date(), isPrivate: false, groupStageFormat: MatchFormat.megaTie, roundFormat: MatchFormat.nineGames, loserRoundFormat: MatchFormat.nineGamesDecisivePoint, groupStageSortMode: GroupStageOrderingMode.snake, groupStageCount: 2, rankSourceDate: Date(), dayDuration: 5, teamCount: 3, teamSorting: TeamSortingType.rank, federalCategory: TournamentCategory.mix, federalLevelCategory: TournamentLevel.p1000, federalAgeCategory: FederalTournamentAge.a45, closedRegistrationDate: Date(), groupStageAdditionalQualified: 4, courtCount: 9, prioritizeClubMembers: true, qualifiedPerGroupStage: 1, teamsPerGroupStage: 2, entryFee: 30.0, additionalEstimationDuration: 5, isDeleted: true, publishTeams: true, publishSummons: true, publishGroupStages: true, publishBrackets: true) let tournament = Tournament(event: eventId, name: "RG Homme", startDate: Date(), endDate: nil, creationDate: Date(), isPrivate: false, groupStageFormat: MatchFormat.megaTie, roundFormat: MatchFormat.nineGames, loserRoundFormat: MatchFormat.nineGamesDecisivePoint, groupStageSortMode: GroupStageOrderingMode.snake, groupStageCount: 2, rankSourceDate: Date(), dayDuration: 5, teamCount: 3, teamSorting: TeamSortingType.rank, federalCategory: TournamentCategory.mix, federalLevelCategory: TournamentLevel.p1000, federalAgeCategory: FederalTournamentAge.a45, closedRegistrationDate: Date(), groupStageAdditionalQualified: 4, courtCount: 9, prioritizeClubMembers: true, qualifiedPerGroupStage: 1, teamsPerGroupStage: 2, entryFee: 30.0, additionalEstimationDuration: 5, isDeleted: true, publishTeams: true, publishSummons: true, publishGroupStages: true, publishBrackets: true, shouldVerifyBracket: true, shouldVerifyGroupStage: true)
let t = try await Store.main.service().post(tournament) let t = try await Store.main.service().post(tournament)
assert(t.event == tournament.event) assert(t.event == tournament.event)
@ -130,7 +130,8 @@ final class ServerDataTests: XCTestCase {
assert(t.publishSummons == tournament.publishSummons) assert(t.publishSummons == tournament.publishSummons)
assert(t.publishGroupStages == tournament.publishGroupStages) assert(t.publishGroupStages == tournament.publishGroupStages)
assert(t.publishBrackets == tournament.publishBrackets) assert(t.publishBrackets == tournament.publishBrackets)
assert(t.shouldVerifyBracket == tournament.shouldVerifyBracket)
assert(t.shouldVerifyGroupStage == tournament.shouldVerifyGroupStage)
} }
func testGroupStage() async throws { func testGroupStage() async throws {

Loading…
Cancel
Save