|
|
|
|
@ -58,6 +58,10 @@ struct TournamentRankView: View { |
|
|
|
|
RowButtonView("Publier le classement", role: .destructive) { |
|
|
|
|
_publishRankings() |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
RowButtonView("Re-publier le classement", role: .destructive) { |
|
|
|
|
_publishRankings() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -78,79 +82,12 @@ struct TournamentRankView: View { |
|
|
|
|
if rankingPublished { |
|
|
|
|
Section { |
|
|
|
|
ForEach(tournament.teamsRanked()) { team in |
|
|
|
|
let key = team.finalRanking! |
|
|
|
|
let key = team.finalRanking ?? 0 |
|
|
|
|
Button { |
|
|
|
|
selectedTeam = team |
|
|
|
|
} label: { |
|
|
|
|
HStack { |
|
|
|
|
VStack(alignment: .trailing) { |
|
|
|
|
VStack(alignment: .trailing, spacing: -8.0) { |
|
|
|
|
ZStack(alignment: .trailing) { |
|
|
|
|
Text(tournament.teamCount.formatted()).hidden() |
|
|
|
|
Text(key.formatted()) |
|
|
|
|
} |
|
|
|
|
.monospacedDigit() |
|
|
|
|
.font(.largeTitle) |
|
|
|
|
.fontWeight(.bold) |
|
|
|
|
Text(key.ordinalFormattedSuffix()).font(.caption) |
|
|
|
|
} |
|
|
|
|
if let index = tournament.indexOf(team: team) { |
|
|
|
|
let rankingDifference = index - (key - 1) |
|
|
|
|
if rankingDifference > 0 { |
|
|
|
|
HStack(spacing: 0.0) { |
|
|
|
|
Text(rankingDifference.formatted(.number.sign(strategy: .always()))) |
|
|
|
|
.monospacedDigit() |
|
|
|
|
Image(systemName: "arrowtriangle.up.fill") |
|
|
|
|
.imageScale(.small) |
|
|
|
|
} |
|
|
|
|
.foregroundColor(.green) |
|
|
|
|
} else if rankingDifference < 0 { |
|
|
|
|
HStack(spacing: 0.0) { |
|
|
|
|
Text(rankingDifference.formatted(.number.sign(strategy: .always()))) |
|
|
|
|
.monospacedDigit() |
|
|
|
|
Image(systemName: "arrowtriangle.down.fill") |
|
|
|
|
.imageScale(.small) |
|
|
|
|
} |
|
|
|
|
.foregroundColor(.red) |
|
|
|
|
} else { |
|
|
|
|
Text("--") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Divider() |
|
|
|
|
|
|
|
|
|
VStack(alignment: .leading) { |
|
|
|
|
if let name = team.name { |
|
|
|
|
Text(name).foregroundStyle(.secondary) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ForEach(team.players()) { player in |
|
|
|
|
VStack(alignment: .leading, spacing: -4.0) { |
|
|
|
|
Text(player.playerLabel()).bold() |
|
|
|
|
HStack(alignment: .firstTextBaseline, spacing: 0.0) { |
|
|
|
|
Text(player.rankLabel()) |
|
|
|
|
if let rank = player.getRank() { |
|
|
|
|
Text(rank.ordinalFormattedSuffix()) |
|
|
|
|
.font(.caption) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if tournament.isAnimation() == false { |
|
|
|
|
Spacer() |
|
|
|
|
VStack(alignment: .trailing) { |
|
|
|
|
HStack(alignment: .lastTextBaseline, spacing: 0.0) { |
|
|
|
|
Text(tournament.tournamentLevel.points(for: key - 1, count: tournament.teamCount).formatted(.number.sign(strategy: .always()))) |
|
|
|
|
Text("pts").font(.caption) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.frame(maxWidth: .infinity) |
|
|
|
|
TeamRankCellView(team: team, key: key) |
|
|
|
|
.frame(maxWidth: .infinity) |
|
|
|
|
} |
|
|
|
|
.contentShape(Rectangle()) |
|
|
|
|
.buttonStyle(.plain) |
|
|
|
|
@ -158,15 +95,16 @@ struct TournamentRankView: View { |
|
|
|
|
} footer: { |
|
|
|
|
Text("Vous pouvez appuyer sur une ligne pour éditer manuellement le classement calculé par Padel Club.") |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
let keys = rankings.keys.sorted() |
|
|
|
|
ForEach(keys, id: \.self) { key in |
|
|
|
|
if let rankedTeams = rankings[key] { |
|
|
|
|
ForEach(rankedTeams) { team in |
|
|
|
|
TeamRankCellView(team: team, key: key) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// let keys = rankings.keys.sorted() |
|
|
|
|
// ForEach(keys, id: \.self) { key in |
|
|
|
|
// if let rankedTeams = rankings[key] { |
|
|
|
|
// ForEach(rankedTeams) { team in |
|
|
|
|
// |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
} |
|
|
|
|
.alert("Position", isPresented: isEditingTeam) { |
|
|
|
|
if let selectedTeam { |
|
|
|
|
@ -198,7 +136,6 @@ struct TournamentRankView: View { |
|
|
|
|
calculating = true |
|
|
|
|
Task { |
|
|
|
|
await _calculateRankings() |
|
|
|
|
_publishRankings() |
|
|
|
|
calculating = false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -215,6 +152,83 @@ struct TournamentRankView: View { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct TeamRankCellView: View { |
|
|
|
|
@Environment(Tournament.self) var tournament: Tournament |
|
|
|
|
let team: TeamRegistration |
|
|
|
|
let key: Int |
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
|
HStack { |
|
|
|
|
VStack(alignment: .trailing) { |
|
|
|
|
VStack(alignment: .trailing, spacing: -8.0) { |
|
|
|
|
ZStack(alignment: .trailing) { |
|
|
|
|
Text(tournament.teamCount.formatted()).hidden() |
|
|
|
|
Text(key.formatted()) |
|
|
|
|
} |
|
|
|
|
.monospacedDigit() |
|
|
|
|
.font(.largeTitle) |
|
|
|
|
.fontWeight(.bold) |
|
|
|
|
Text(key.ordinalFormattedSuffix()).font(.caption) |
|
|
|
|
} |
|
|
|
|
if let index = tournament.indexOf(team: team) { |
|
|
|
|
let rankingDifference = index - (key - 1) |
|
|
|
|
if rankingDifference > 0 { |
|
|
|
|
HStack(spacing: 0.0) { |
|
|
|
|
Text(rankingDifference.formatted(.number.sign(strategy: .always()))) |
|
|
|
|
.monospacedDigit() |
|
|
|
|
Image(systemName: "arrowtriangle.up.fill") |
|
|
|
|
.imageScale(.small) |
|
|
|
|
} |
|
|
|
|
.foregroundColor(.green) |
|
|
|
|
} else if rankingDifference < 0 { |
|
|
|
|
HStack(spacing: 0.0) { |
|
|
|
|
Text(rankingDifference.formatted(.number.sign(strategy: .always()))) |
|
|
|
|
.monospacedDigit() |
|
|
|
|
Image(systemName: "arrowtriangle.down.fill") |
|
|
|
|
.imageScale(.small) |
|
|
|
|
} |
|
|
|
|
.foregroundColor(.red) |
|
|
|
|
} else { |
|
|
|
|
Text("--") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Divider() |
|
|
|
|
|
|
|
|
|
VStack(alignment: .leading) { |
|
|
|
|
if let name = team.name { |
|
|
|
|
Text(name).foregroundStyle(.secondary) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ForEach(team.players()) { player in |
|
|
|
|
VStack(alignment: .leading, spacing: -4.0) { |
|
|
|
|
Text(player.playerLabel()).bold() |
|
|
|
|
HStack(alignment: .firstTextBaseline, spacing: 0.0) { |
|
|
|
|
Text(player.rankLabel()) |
|
|
|
|
if let rank = player.getRank() { |
|
|
|
|
Text(rank.ordinalFormattedSuffix()) |
|
|
|
|
.font(.caption) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if tournament.isAnimation() == false && key > 0 { |
|
|
|
|
Spacer() |
|
|
|
|
VStack(alignment: .trailing) { |
|
|
|
|
HStack(alignment: .lastTextBaseline, spacing: 0.0) { |
|
|
|
|
Text(tournament.tournamentLevel.points(for: key - 1, count: tournament.teamCount).formatted(.number.sign(strategy: .always()))) |
|
|
|
|
Text("pts").font(.caption) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private func _publishRankings() { |
|
|
|
|
rankings.keys.sorted().forEach { rank in |
|
|
|
|
if let rankedTeams = rankings[rank] { |
|
|
|
|
|