|
|
|
@ -180,7 +180,7 @@ struct InscriptionManagerView: View { |
|
|
|
return _simpleHash(ids: ids1) != _simpleHash(ids: ids2) |
|
|
|
return _simpleHash(ids: ids1) != _simpleHash(ids: ids2) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func _setHash() { |
|
|
|
private func _setHash(currentSelectedSortedTeams: [TeamRegistration]? = nil) { |
|
|
|
#if _DEBUG_TIME //DEBUGING TIME |
|
|
|
#if _DEBUG_TIME //DEBUGING TIME |
|
|
|
let start = Date() |
|
|
|
let start = Date() |
|
|
|
defer { |
|
|
|
defer { |
|
|
|
@ -188,18 +188,17 @@ struct InscriptionManagerView: View { |
|
|
|
print("func _setHash", duration.formatted(.units(allowed: [.seconds, .milliseconds]))) |
|
|
|
print("func _setHash", duration.formatted(.units(allowed: [.seconds, .milliseconds]))) |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
let selectedSortedTeams = tournament.selectedSortedTeams() |
|
|
|
let selectedSortedTeams = currentSelectedSortedTeams == nil ? tournament.selectedSortedTeams() : currentSelectedSortedTeams! |
|
|
|
if self.teamsHash == nil, selectedSortedTeams.isEmpty == false { |
|
|
|
if self.teamsHash == nil, selectedSortedTeams.isEmpty == false { |
|
|
|
self.teamsHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) |
|
|
|
self.teamsHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) |
|
|
|
} |
|
|
|
} |
|
|
|
self.registrationIssues = nil |
|
|
|
self.registrationIssues = nil |
|
|
|
DispatchQueue.main.async { |
|
|
|
DispatchQueue.main.async { |
|
|
|
self.registrationIssues = tournament.registrationIssues() |
|
|
|
self.registrationIssues = tournament.registrationIssues(selectedTeams: selectedSortedTeams) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func _handleHashDiff() { |
|
|
|
private func _handleHashDiff(selectedSortedTeams: [TeamRegistration]) { |
|
|
|
let selectedSortedTeams = tournament.selectedSortedTeams() |
|
|
|
|
|
|
|
let newHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) |
|
|
|
let newHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) |
|
|
|
if (self.teamsHash != nil && newHash != teamsHash!) || (self.teamsHash == nil && selectedSortedTeams.isEmpty == false) { |
|
|
|
if (self.teamsHash != nil && newHash != teamsHash!) || (self.teamsHash == nil && selectedSortedTeams.isEmpty == false) { |
|
|
|
self.teamsHash = newHash |
|
|
|
self.teamsHash = newHash |
|
|
|
@ -225,9 +224,10 @@ struct InscriptionManagerView: View { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
var body: some View { |
|
|
|
Group { |
|
|
|
let selectedSortedTeams = tournament.selectedSortedTeams() |
|
|
|
if tournament.unsortedTeams().isEmpty == false { |
|
|
|
return Group { |
|
|
|
_teamRegisteredView() |
|
|
|
if tournament.unsortedTeamsCount() > 0 { |
|
|
|
|
|
|
|
_teamRegisteredView(selectedSortedTeams: selectedSortedTeams) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
List { |
|
|
|
List { |
|
|
|
|
|
|
|
|
|
|
|
@ -263,10 +263,10 @@ struct InscriptionManagerView: View { |
|
|
|
await _refreshList() |
|
|
|
await _refreshList() |
|
|
|
} |
|
|
|
} |
|
|
|
.onAppear { |
|
|
|
.onAppear { |
|
|
|
_setHash() |
|
|
|
_setHash(currentSelectedSortedTeams: selectedSortedTeams) |
|
|
|
} |
|
|
|
} |
|
|
|
.onDisappear { |
|
|
|
.onDisappear { |
|
|
|
_handleHashDiff() |
|
|
|
_handleHashDiff(selectedSortedTeams: selectedSortedTeams) |
|
|
|
} |
|
|
|
} |
|
|
|
.sheet(isPresented: $isLearningMore) { |
|
|
|
.sheet(isPresented: $isLearningMore) { |
|
|
|
LearnMoreSheetView(tournament: tournament) |
|
|
|
LearnMoreSheetView(tournament: tournament) |
|
|
|
@ -490,47 +490,43 @@ struct InscriptionManagerView: View { |
|
|
|
tournament.unsortedPlayers() |
|
|
|
tournament.unsortedPlayers() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var sortedTeams: [TeamRegistration] { |
|
|
|
func sortedTeams(selectedSortedTeams: [TeamRegistration]) -> [TeamRegistration] { |
|
|
|
if filterMode == .waiting { |
|
|
|
if filterMode == .waiting { |
|
|
|
return tournament.waitingListSortedTeams() |
|
|
|
return tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return tournament.sortedTeams() |
|
|
|
return tournament.sortedTeams(selectedSortedTeams: selectedSortedTeams) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var filteredTeams: [TeamRegistration] { |
|
|
|
func filteredTeams(sortedTeams: [TeamRegistration]) -> [TeamRegistration] { |
|
|
|
|
|
|
|
let filtered = sortedTeams.lazy.filter { team in |
|
|
|
var teams = sortedTeams |
|
|
|
switch filterMode { |
|
|
|
switch filterMode { |
|
|
|
case .wildcardBracket: |
|
|
|
case .wildcardBracket: |
|
|
|
return team.wildCardBracket |
|
|
|
teams = teams.filter({ $0.wildCardBracket }) |
|
|
|
case .wildcardGroupStage: |
|
|
|
case .wildcardGroupStage: |
|
|
|
return team.wildCardGroupStage |
|
|
|
teams = teams.filter({ $0.wildCardGroupStage }) |
|
|
|
case .walkOut: |
|
|
|
case .walkOut: |
|
|
|
return team.walkOut |
|
|
|
teams = teams.filter({ $0.walkOut }) |
|
|
|
case .bracket: |
|
|
|
case .bracket: |
|
|
|
return team.inRound() && !team.inGroupStage() |
|
|
|
teams = teams.filter({ $0.inRound() && $0.inGroupStage() == false }) |
|
|
|
case .groupStage: |
|
|
|
case .groupStage: |
|
|
|
return team.inGroupStage() |
|
|
|
teams = teams.filter({ $0.inGroupStage() }) |
|
|
|
case .notImported: |
|
|
|
case .notImported: |
|
|
|
return !team.isImported() |
|
|
|
teams = teams.filter({ $0.isImported() == false }) |
|
|
|
case .registeredLocally: |
|
|
|
case .registeredLocally: |
|
|
|
return !team.hasRegisteredOnline() |
|
|
|
teams = teams.filter({ $0.hasRegisteredOnline() == false }) |
|
|
|
case .registeredOnline: |
|
|
|
case .registeredOnline: |
|
|
|
return team.hasRegisteredOnline() |
|
|
|
teams = teams.filter({ $0.hasRegisteredOnline() == true }) |
|
|
|
default: |
|
|
|
default: |
|
|
|
return true |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if sortingMode == .registrationDate { |
|
|
|
let sorted = sortingMode == .registrationDate |
|
|
|
teams = teams.sorted(by: \.computedRegistrationDate) |
|
|
|
? filtered.sorted(by: { $0.computedRegistrationDate < $1.computedRegistrationDate }) |
|
|
|
} |
|
|
|
: Array(filtered) |
|
|
|
|
|
|
|
|
|
|
|
if byDecreasingOrdering { |
|
|
|
return byDecreasingOrdering ? sorted.reversed() : sorted |
|
|
|
return teams.reversed() |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return teams |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// private func _fixModel() { |
|
|
|
// private func _fixModel() { |
|
|
|
@ -572,12 +568,10 @@ struct InscriptionManagerView: View { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func _teamRegisteredView() -> some View { |
|
|
|
private func _teamRegisteredView(selectedSortedTeams: [TeamRegistration]) -> some View { |
|
|
|
List { |
|
|
|
List { |
|
|
|
let selectedSortedTeams = tournament.selectedSortedTeams() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if presentSearch == false { |
|
|
|
if presentSearch == false { |
|
|
|
_informationView() |
|
|
|
_informationView(for: selectedSortedTeams) |
|
|
|
|
|
|
|
|
|
|
|
if tournament.isAnimation() == false { |
|
|
|
if tournament.isAnimation() == false { |
|
|
|
_rankHandlerView() |
|
|
|
_rankHandlerView() |
|
|
|
@ -585,7 +579,8 @@ struct InscriptionManagerView: View { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let teams = searchField.isEmpty ? filteredTeams : filteredTeams.filter({ $0.contains(searchField.canonicalVersion) }) |
|
|
|
let sortedTeams = sortedTeams(selectedSortedTeams: selectedSortedTeams) |
|
|
|
|
|
|
|
let teams = searchField.isEmpty ? filteredTeams(sortedTeams: sortedTeams) : filteredTeams(sortedTeams: sortedTeams).filter({ $0.contains(searchField.canonicalVersion) }) |
|
|
|
|
|
|
|
|
|
|
|
if teams.isEmpty && searchField.isEmpty == false { |
|
|
|
if teams.isEmpty && searchField.isEmpty == false { |
|
|
|
ContentUnavailableView { |
|
|
|
ContentUnavailableView { |
|
|
|
@ -622,7 +617,7 @@ struct InscriptionManagerView: View { |
|
|
|
EditingTeamView(team: team) |
|
|
|
EditingTeamView(team: team) |
|
|
|
.environment(tournament) |
|
|
|
.environment(tournament) |
|
|
|
} label: { |
|
|
|
} label: { |
|
|
|
TeamRowView(team: team) |
|
|
|
TeamRowView(team: team, teamIndex: teamIndex) |
|
|
|
} |
|
|
|
} |
|
|
|
.swipeActions(edge: .trailing, allowsFullSwipe: true) { |
|
|
|
.swipeActions(edge: .trailing, allowsFullSwipe: true) { |
|
|
|
if tournament.enableOnlineRegistration == false { |
|
|
|
if tournament.enableOnlineRegistration == false { |
|
|
|
@ -735,18 +730,18 @@ struct InscriptionManagerView: View { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func _teamCountForFilterMode(filterMode: FilterMode) -> String { |
|
|
|
private func _teamCountForFilterMode(filterMode: FilterMode, in teams: [TeamRegistration]) -> String { |
|
|
|
switch filterMode { |
|
|
|
switch filterMode { |
|
|
|
case .wildcardBracket: |
|
|
|
case .wildcardBracket: |
|
|
|
return tournament.selectedSortedTeams().filter({ $0.wildCardBracket }).count.formatted() |
|
|
|
return teams.filter({ $0.wildCardBracket }).count.formatted() |
|
|
|
case .wildcardGroupStage: |
|
|
|
case .wildcardGroupStage: |
|
|
|
return tournament.selectedSortedTeams().filter({ $0.wildCardGroupStage }).count.formatted() |
|
|
|
return teams.filter({ $0.wildCardGroupStage }).count.formatted() |
|
|
|
case .all: |
|
|
|
case .all: |
|
|
|
return unsortedTeamsWithoutWO.count.formatted() |
|
|
|
return unsortedTeamsWithoutWO.count.formatted() |
|
|
|
case .bracket: |
|
|
|
case .bracket: |
|
|
|
return tournament.selectedSortedTeams().filter({ $0.inRound() && $0.inGroupStage() == false }).count.formatted() |
|
|
|
return teams.filter({ $0.inRound() && $0.inGroupStage() == false }).count.formatted() |
|
|
|
case .groupStage: |
|
|
|
case .groupStage: |
|
|
|
return tournament.selectedSortedTeams().filter({ $0.inGroupStage() }).count.formatted() |
|
|
|
return teams.filter({ $0.inGroupStage() }).count.formatted() |
|
|
|
case .walkOut: |
|
|
|
case .walkOut: |
|
|
|
let wo = walkoutTeams.count.formatted() |
|
|
|
let wo = walkoutTeams.count.formatted() |
|
|
|
return wo |
|
|
|
return wo |
|
|
|
@ -754,20 +749,20 @@ struct InscriptionManagerView: View { |
|
|
|
let waiting: Int = max(0, unsortedTeamsWithoutWO.count - tournament.teamCount) |
|
|
|
let waiting: Int = max(0, unsortedTeamsWithoutWO.count - tournament.teamCount) |
|
|
|
return waiting.formatted() |
|
|
|
return waiting.formatted() |
|
|
|
case .notImported: |
|
|
|
case .notImported: |
|
|
|
let notImported: Int = max(0, sortedTeams.filter({ $0.isImported() == false }).count) |
|
|
|
let notImported: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.isImported() == false }).count) |
|
|
|
return notImported.formatted() |
|
|
|
return notImported.formatted() |
|
|
|
case .registeredLocally: |
|
|
|
case .registeredLocally: |
|
|
|
let registeredLocally: Int = max(0, sortedTeams.filter({ $0.hasRegisteredOnline() == false }).count) |
|
|
|
let registeredLocally: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.hasRegisteredOnline() == false }).count) |
|
|
|
return registeredLocally.formatted() |
|
|
|
return registeredLocally.formatted() |
|
|
|
case .registeredOnline: |
|
|
|
case .registeredOnline: |
|
|
|
let registeredOnline: Int = max(0, sortedTeams.filter({ $0.hasRegisteredOnline() }).count) |
|
|
|
let registeredOnline: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.hasRegisteredOnline() }).count) |
|
|
|
return registeredOnline.formatted() |
|
|
|
return registeredOnline.formatted() |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ViewBuilder |
|
|
|
@ViewBuilder |
|
|
|
private func _informationView() -> some View { |
|
|
|
private func _informationView(for teams: [TeamRegistration]) -> some View { |
|
|
|
Section { |
|
|
|
Section { |
|
|
|
HStack { |
|
|
|
HStack { |
|
|
|
// VStack(alignment: .leading, spacing: 0) { |
|
|
|
// VStack(alignment: .leading, spacing: 0) { |
|
|
|
@ -781,7 +776,7 @@ struct InscriptionManagerView: View { |
|
|
|
// } |
|
|
|
// } |
|
|
|
// |
|
|
|
// |
|
|
|
ForEach([FilterMode.all, FilterMode.waiting, FilterMode.walkOut]) { filterMode in |
|
|
|
ForEach([FilterMode.all, FilterMode.waiting, FilterMode.walkOut]) { filterMode in |
|
|
|
_filterModeView(filterMode: filterMode) |
|
|
|
_filterModeView(filterMode: filterMode, in: teams) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Button { |
|
|
|
Button { |
|
|
|
@ -809,7 +804,7 @@ struct InscriptionManagerView: View { |
|
|
|
.listRowSeparator(.hidden) |
|
|
|
.listRowSeparator(.hidden) |
|
|
|
HStack { |
|
|
|
HStack { |
|
|
|
ForEach([FilterMode.groupStage, FilterMode.bracket, FilterMode.wildcardGroupStage, FilterMode.wildcardBracket]) { filterMode in |
|
|
|
ForEach([FilterMode.groupStage, FilterMode.bracket, FilterMode.wildcardGroupStage, FilterMode.wildcardBracket]) { filterMode in |
|
|
|
_filterModeView(filterMode: filterMode) |
|
|
|
_filterModeView(filterMode: filterMode, in: teams) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
.padding(.bottom, -4) |
|
|
|
.padding(.bottom, -4) |
|
|
|
@ -883,7 +878,7 @@ struct InscriptionManagerView: View { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private func _filterModeView(filterMode: FilterMode) -> some View { |
|
|
|
private func _filterModeView(filterMode: FilterMode, in teams: [TeamRegistration]) -> some View { |
|
|
|
|
|
|
|
|
|
|
|
Button { |
|
|
|
Button { |
|
|
|
if self.filterMode == filterMode { |
|
|
|
if self.filterMode == filterMode { |
|
|
|
@ -894,7 +889,7 @@ struct InscriptionManagerView: View { |
|
|
|
} label: { |
|
|
|
} label: { |
|
|
|
VStack(alignment: .center, spacing: -2) { |
|
|
|
VStack(alignment: .center, spacing: -2) { |
|
|
|
Text(filterMode.localizedLabel(.short)).font(.caption).padding(.horizontal, -8) |
|
|
|
Text(filterMode.localizedLabel(.short)).font(.caption).padding(.horizontal, -8) |
|
|
|
Text(_teamCountForFilterMode(filterMode: filterMode)).font(.largeTitle) |
|
|
|
Text(_teamCountForFilterMode(filterMode: filterMode, in: teams)).font(.largeTitle) |
|
|
|
} |
|
|
|
} |
|
|
|
.frame(maxWidth: .infinity) |
|
|
|
.frame(maxWidth: .infinity) |
|
|
|
.contentShape(Rectangle()) |
|
|
|
.contentShape(Rectangle()) |
|
|
|
|