Merge branch 'main'

release
Raz 1 year ago
commit e318df1eb5
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 8
      PadelClub/Data/TeamRegistration.swift
  3. 2
      PadelClub/Data/Tournament.swift
  4. 45
      PadelClub/Utils/Patcher.swift
  5. 49
      PadelClub/Views/Calling/TeamsCallingView.swift
  6. 2
      PadelClub/Views/Navigation/Umpire/UmpireView.swift
  7. 5
      PadelClub/Views/Shared/ImportedPlayerView.swift
  8. 12
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  9. 16
      PadelClub/Views/Team/EditingTeamView.swift
  10. 11
      PadelClub/Views/Tournament/Screen/BroadcastView.swift

@ -1985,7 +1985,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.5; MARKETING_VERSION = 1.0.6;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_SWIFT_FLAGS = "-Onone"; OTHER_SWIFT_FLAGS = "-Onone";
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
@ -2033,7 +2033,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.5; MARKETING_VERSION = 1.0.6;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-function-bodies=5 -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=50"; OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-function-bodies=5 -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=50";
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;

@ -498,6 +498,14 @@ final class TeamRegistration: ModelObject, Storable {
return self.tournamentStore.matches.first(where: { $0.round == initialRoundObject.id && $0.index == bracketPosition / 2 }) return self.tournamentStore.matches.first(where: { $0.round == initialRoundObject.id && $0.index == bracketPosition / 2 })
} }
func toggleSummonConfirmation() {
if confirmationDate == nil { confirmationDate = Date() }
else { confirmationDate = nil }
}
func didConfirmSummon() -> Bool {
confirmationDate != nil
}
func tournamentObject() -> Tournament? { func tournamentObject() -> Tournament? {
return Store.main.findById(tournament) return Store.main.findById(tournament)

@ -113,7 +113,7 @@ final class Tournament : ModelObject, Storable {
self.startDate = startDate self.startDate = startDate
self.endDate = endDate self.endDate = endDate
self.creationDate = creationDate self.creationDate = creationDate
self.isPrivate = isPrivate self.isPrivate = Guard.main.purchasedTransactions.isEmpty
self.groupStageFormat = groupStageFormat self.groupStageFormat = groupStageFormat
self.roundFormat = roundFormat self.roundFormat = roundFormat
self.loserRoundFormat = loserRoundFormat self.loserRoundFormat = loserRoundFormat

@ -15,6 +15,7 @@ enum PatchError: Error {
enum Patch: String, CaseIterable { enum Patch: String, CaseIterable {
case alexisLeDu case alexisLeDu
case importDataFromDevToProd case importDataFromDevToProd
case fixMissingMatches
var id: String { var id: String {
return "padelclub.app.patch.\(self.rawValue)" return "padelclub.app.patch.\(self.rawValue)"
@ -45,6 +46,7 @@ class Patcher {
switch patch { switch patch {
case .alexisLeDu: self._patchAlexisLeDu() case .alexisLeDu: self._patchAlexisLeDu()
case .importDataFromDevToProd: try self._importDataFromDev() case .importDataFromDevToProd: try self._importDataFromDev()
case .fixMissingMatches: self._patchMissingMatches()
} }
} }
@ -115,5 +117,48 @@ class Patcher {
} }
} }
fileprivate static func _patchMissingMatches() {
guard let url = StoreCenter.main.synchronizationApiURL else {
return
}
guard url == "https://padelclub.app/roads/" else {
return
}
let services = Services(url: url)
for tournament in DataStore.shared.tournaments {
let store = tournament.tournamentStore
let identifier = StoreIdentifier(value: tournament.id, parameterName: "tournament")
Task {
do {
// if nothing is online we upload the data
let matches: [Match] = try await services.get(identifier: identifier)
if matches.isEmpty {
store.matches.insertAllIntoCurrentService()
}
let playerRegistrations: [PlayerRegistration] = try await services.get(identifier: identifier)
if playerRegistrations.isEmpty {
store.playerRegistrations.insertAllIntoCurrentService()
}
let teamScores: [TeamScore] = try await services.get(identifier: identifier)
if teamScores.isEmpty {
store.teamScores.insertAllIntoCurrentService()
}
} catch {
Logger.error(error)
}
}
}
}
} }

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct TeamsCallingView: View { struct TeamsCallingView: View {
@Environment(Tournament.self) var tournament: Tournament @Environment(Tournament.self) var tournament: Tournament
@ -15,7 +16,23 @@ struct TeamsCallingView: View {
let teams = tournament.selectedSortedTeams() let teams = tournament.selectedSortedTeams()
Section { Section {
ForEach(teams) { team in ForEach(teams) { team in
TeamRowView(team: team, displayCallDate: true) Menu {
_menuOptions(team: team)
} label: {
HStack {
TeamRowView(team: team, displayCallDate: true)
if team.called() {
Spacer()
Menu {
_menuOptions(team: team)
} label: {
LabelOptions().labelStyle(.iconOnly)
}
}
}
}
.buttonStyle(.plain)
.listRowView(isActive: team.didConfirmSummon(), color: .green, hideColorVariation: true)
} }
} }
} }
@ -25,4 +42,34 @@ struct TeamsCallingView: View {
.toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar)
} }
@ViewBuilder
func _menuOptions(team: TeamRegistration) -> some View {
Button {
team.toggleSummonConfirmation()
do {
try self.tournament.tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
} label: {
if team.didConfirmSummon() {
Label("Confirmation reçue", systemImage: "checkmark.circle.fill").foregroundStyle(.green)
} else {
Label("Confirmation reçue", systemImage: "circle").foregroundStyle(.logoRed)
}
}
Divider()
Button(role: .destructive) {
team.callDate = nil
do {
try self.tournament.tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
} label: {
Text("Effacer la date de convocation")
}
}
} }

@ -56,7 +56,7 @@ struct UmpireView: View {
Section { Section {
if let currentPlayerData { if let currentPlayerData {
//todo palmares //todo palmares
ImportedPlayerView(player: currentPlayerData) ImportedPlayerView(player: currentPlayerData, showProgression: true)
// NavigationLink { // NavigationLink {
// //
// } label: { // } label: {

@ -11,7 +11,7 @@ struct ImportedPlayerView: View {
let player: PlayerHolder let player: PlayerHolder
var index: Int? = nil var index: Int? = nil
var showFemaleInMaleAssimilation: Bool = false var showFemaleInMaleAssimilation: Bool = false
@State var showProgression: Bool = false var showProgression: Bool = false
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
@ -54,7 +54,7 @@ struct ImportedPlayerView: View {
} }
} }
if player.getProgression() != 0 { if showProgression, player.getProgression() != 0 {
HStack(alignment: .top, spacing: 2) { HStack(alignment: .top, spacing: 2) {
Text("(") Text("(")
Text(player.getProgression().formatted(.number.sign(strategy: .always()))) Text(player.getProgression().formatted(.number.sign(strategy: .always())))
@ -77,6 +77,7 @@ struct ImportedPlayerView: View {
} }
} }
} }
.lineLimit(1)
if showFemaleInMaleAssimilation, let assimilatedAsMaleRank = player.getAssimilatedAsMaleRank() { if showFemaleInMaleAssimilation, let assimilatedAsMaleRank = player.getAssimilatedAsMaleRank() {
HStack(alignment: .top, spacing: 2) { HStack(alignment: .top, spacing: 2) {

@ -364,7 +364,7 @@ struct MySearchView: View {
let array = Array(searchViewModel.selectedPlayers) let array = Array(searchViewModel.selectedPlayers)
Section { Section {
ForEach(array) { player in ForEach(array) { player in
ImportedPlayerView(player: player, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
.onDelete { indexSet in .onDelete { indexSet in
for index in indexSet { for index in indexSet {
@ -379,7 +379,7 @@ struct MySearchView: View {
} else { } else {
Section { Section {
ForEach(players, id: \.self) { player in ForEach(players, id: \.self) { player in
ImportedPlayerView(player: player, index: nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, index: nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
} header: { } header: {
if players.isEmpty == false { if players.isEmpty == false {
@ -398,7 +398,7 @@ struct MySearchView: View {
Button { Button {
searchViewModel.selectedPlayers.insert(player) searchViewModel.selectedPlayers.insert(player)
} label: { } label: {
ImportedPlayerView(player: player, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
} }
@ -412,7 +412,7 @@ struct MySearchView: View {
Section { Section {
ForEach(players.indices, id: \.self) { index in ForEach(players.indices, id: \.self) { index in
let player = players[index] let player = players[index]
ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
} header: { } header: {
if players.isEmpty == false { if players.isEmpty == false {
@ -429,13 +429,13 @@ struct MySearchView: View {
Button { Button {
searchViewModel.selectedPlayers.insert(player) searchViewModel.selectedPlayers.insert(player)
} label: { } label: {
ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
.contentShape(Rectangle()) .contentShape(Rectangle())
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.buttonStyle(.plain) .buttonStyle(.plain)
} else { } else {
ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation) ImportedPlayerView(player: player, index: searchViewModel.showIndex() ? (index + 1) : nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
} }
} }
} header: { } header: {

@ -76,6 +76,22 @@ struct EditingTeamView: View {
} label: { } label: {
Text("Convocation") Text("Convocation")
} }
Button {
team.toggleSummonConfirmation()
do {
try self.tournament.tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
} label: {
if team.didConfirmSummon() {
Label("Confirmation reçue", systemImage: "checkmark.circle.fill").foregroundStyle(.green)
} else {
Label("Confirmation reçue", systemImage: "circle").foregroundStyle(.logoRed)
}
}
} else { } else {
Text("Cette équipe n'a pas été convoquée") Text("Cette équipe n'a pas été convoquée")
} }

@ -108,9 +108,18 @@ struct BroadcastView: View {
Section { Section {
Toggle(isOn: $tournament.isPrivate) { Toggle(isOn: $tournament.isPrivate) {
Text("Tournoi privé") Text("Tournoi privé")
if (tournament.isPrivate && Guard.main.purchasedTransactions.isEmpty) {
Text("Vous devez disposer d'une offre pour rendre publique ce tournoi.")
.foregroundStyle(.logoRed)
}
} }
#if DEBUG
#else
.disabled((tournament.isPrivate && Guard.main.purchasedTransactions.isEmpty))
#endif
} footer: { } footer: {
let footerString = "Le tournoi sera masqué sur le site [Padel Club](\(URLs.main.rawValue))" let verb : String = tournament.isPrivate ? "est" : "sera"
let footerString = " Le tournoi \(verb) masqué sur le site [Padel Club](\(URLs.main.rawValue))"
Text(.init(footerString)) Text(.init(footerString))
} }

Loading…
Cancel
Save