@ -51,7 +51,6 @@ struct InscriptionManagerView: View {
@ State private var pasteString : String ?
@ State private var pasteString : String ?
@ State private var registrationIssues : Int ? = nil
@ State private var registrationIssues : Int ? = nil
@ State private var refreshResult : String ? = nil
@ State private var refreshResult : String ? = nil
@ State private var refreshInProgress : Bool = false
@ State private var refreshStatus : Bool ?
@ State private var refreshStatus : Bool ?
@ State private var showLegendView : Bool = false
@ State private var showLegendView : Bool = false
@ -180,7 +179,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 // D E B U G I N G T I M E
#if _DEBUG_TIME // D E B U G I N G T I M E
let start = Date ( )
let start = Date ( )
defer {
defer {
@ -188,18 +187,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 {
Task {
self . registrationIssues = tournament . registrationIssues ( )
self . registrationIssues = await 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 +223,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 {
@ -248,7 +247,7 @@ struct InscriptionManagerView: View {
if tournament . enableOnlineRegistration {
if tournament . enableOnlineRegistration {
RowButtonView ( " Rafraîchir la liste " , cornerRadius : 20 ) {
RowButtonView ( " Rafraîchir la liste " , cornerRadius : 20 ) {
await _refreshList ( )
await _refreshList ( forced : true )
}
}
} else if tournament . onlineRegistrationCanBeEnabled ( ) {
} else if tournament . onlineRegistrationCanBeEnabled ( ) {
RowButtonView ( " Inscription en ligne " ) {
RowButtonView ( " Inscription en ligne " ) {
@ -259,14 +258,19 @@ struct InscriptionManagerView: View {
}
}
}
}
}
}
. task {
await _refreshList ( forced : false )
}
. refreshable {
. refreshable {
await _refreshList ( )
await _refreshList ( forced : true )
}
}
. onAppear {
. onAppear {
_setHash ( )
if tournament . enableOnlineRegistration = = false || refreshStatus = = true {
_setHash ( currentSelectedSortedTeams : selectedSortedTeams )
}
}
}
. onDisappear {
. onDisappear {
_handleHashDiff ( )
_handleHashDiff ( selectedSortedTeams : selectedSortedTeams )
}
}
. sheet ( isPresented : $ isLearningMore ) {
. sheet ( isPresented : $ isLearningMore ) {
LearnMoreSheetView ( tournament : tournament )
LearnMoreSheetView ( tournament : tournament )
@ -490,47 +494,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
}
}
}
// p r i v a t e f u n c _ f i x M o d e l ( ) {
// p r i v a t e f u n c _ f i x M o d e l ( ) {
@ -546,38 +546,36 @@ struct InscriptionManagerView: View {
// t r y ? t o u r n a m e n t S t o r e . p l a y e r R e g i s t r a t i o n s . a d d O r U p d a t e ( c o n t e n t O f s : p l a y e r s )
// t r y ? t o u r n a m e n t S t o r e . p l a y e r R e g i s t r a t i o n s . a d d O r U p d a t e ( c o n t e n t O f s : p l a y e r s )
// }
// }
//
//
private func _refreshList ( ) async {
private func _refreshList ( forced : Bool ) async {
if refreshInProgress { return }
if refreshStatus = = true , forced = = false { return }
if tournament . enableOnlineRegistration = = false { return }
if tournament . hasEnded ( ) { return }
if tournament . refreshInProgress { return }
refreshResult = nil
refreshResult = nil
refreshStatus = nil
refreshStatus = nil
refreshInProgress = true
do {
do {
try await self . tournamentStore . playerRegistrations . loadDataFromServerIfAllowed ( clear : true )
try await self . tournamentStore . teamScores . loadDataFromServerIfAllowed ( clear : true )
try await self . tournament . refreshTeamList ( )
try await self . tournamentStore . teamRegistrations . loadDataFromServerIfAllowed ( clear : true )
_setHash ( )
_setHash ( )
self . refreshResult = " l a synchronization a réussi"
self . refreshResult = " L a synchronization a réussi"
self . refreshStatus = true
self . refreshStatus = true
refreshInProgress = false
} catch {
} catch {
Logger . error ( error )
Logger . error ( error )
self . refreshResult = " l a synchronization a échoué"
self . refreshResult = " L a synchronization a échoué"
self . refreshStatus = false
self . refreshStatus = false
refreshInProgress = false
tournament . refreshInProgress = false
}
}
}
}
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 +583,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 +621,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 {
@ -722,7 +721,7 @@ struct InscriptionManagerView: View {
@ ViewBuilder
@ ViewBuilder
private func _rankHandlerView ( ) -> some View {
private func _rankHandlerView ( ) -> some View {
if let mostRecentDate = SourceFileManager . shared . lastDataSourceDate ( ) , let currentRankSourceDate , currentRankSourceDate < mostRecentDate , tournament . hasEnd ed( ) = = false {
if let mostRecentDate = tournament . rankSourceShouldBeRefresh ed( ) {
Section {
Section {
TipView ( rankUpdateTip ) { action in
TipView ( rankUpdateTip ) { action in
self . currentRankSourceDate = mostRecentDate
self . currentRankSourceDate = mostRecentDate
@ -735,18 +734,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 . selectedSortedT eams ( ) . filter ( { $0 . wildCardBracket } ) . count . formatted ( )
return teams . filter ( { $0 . wildCardBracket } ) . count . formatted ( )
case . wildcardGroupStage :
case . wildcardGroupStage :
return tournament . selectedSortedT eams ( ) . 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 . selectedSortedT eams ( ) . filter ( { $0 . inRound ( ) && $0 . inGroupStage ( ) = = false } ) . count . formatted ( )
return teams . filter ( { $0 . inRound ( ) && $0 . inGroupStage ( ) = = false } ) . count . formatted ( )
case . groupStage :
case . groupStage :
return tournament . selectedSortedT eams ( ) . 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 +753,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 {
// V S t a c k ( a l i g n m e n t : . l e a d i n g , s p a c i n g : 0 ) {
// V S t a c k ( a l i g n m e n t : . l e a d i n g , s p a c i n g : 0 ) {
@ -781,7 +780,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 +808,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 )
@ -844,28 +843,21 @@ struct InscriptionManagerView: View {
// }
// }
if tournament . enableOnlineRegistration {
if tournament . enableOnlineRegistration {
Button {
LabeledContent {
Task {
Text ( tournament . unsortedTeams ( ) . filter ( { $0 . hasRegisteredOnline ( ) } ) . count . formatted ( ) )
await _refreshList ( )
. font ( . largeTitle )
}
} label : {
} label : {
LabeledContent {
Text ( " Inscriptions en ligne " )
if refreshInProgress {
if let refreshResult {
ProgressView ( )
Text ( refreshResult ) . foregroundStyle ( . secondary )
} else if let refreshStatus {
} else {
if refreshStatus {
Text ( " " )
Image ( systemName : " checkmark " ) . foregroundStyle ( . green ) . font ( . headline )
} else {
Image ( systemName : " xmark " ) . foregroundStyle ( . logoRed ) . font ( . headline )
}
}
} label : {
Text ( " Récupérer les inscriptions en ligne " )
if let refreshResult {
Text ( refreshResult )
}
}
}
}
}
RowButtonView ( " Rafraîchir les inscriptions en ligne " ) {
await _refreshList ( forced : true )
}
}
}
} header : {
} header : {
HStack {
HStack {
@ -883,7 +875,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 +886,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 ( ) )