@ -9,15 +9,15 @@ import SwiftUI
import TipKit
import TipKit
import LeStorage
import LeStorage
let slideToDeleteTip = SlideToDeleteTip ( )
// l e t s l i d e T o D e l e t e T i p = S l i d e T o D e l e t e T i p ( )
let inscriptionManagerWomanRankTip = InscriptionManagerWomanRankTip ( )
let inscriptionManagerWomanRankTip = InscriptionManagerWomanRankTip ( )
let fileTip = InscriptionManagerFileInputTip ( )
// l e t f i l e T i p = I n s c r i p t i o n M a n a g e r F i l e I n p u t T i p ( )
let pasteTip = InscriptionManagerPasteInputTip ( )
// l e t p a s t e T i p = I n s c r i p t i o n M a n a g e r P a s t e I n p u t T i p ( )
let searchTip = InscriptionManagerSearchInputTip ( )
// l e t s e a r c h T i p = I n s c r i p t i o n M a n a g e r S e a r c h I n p u t T i p ( )
let createTip = InscriptionManagerCreateInputTip ( )
// l e t c r e a t e T i p = I n s c r i p t i o n M a n a g e r C r e a t e I n p u t T i p ( )
let rankUpdateTip = InscriptionManagerRankUpdateTip ( )
let rankUpdateTip = InscriptionManagerRankUpdateTip ( )
let padelBeachExportTip = PadelBeachExportTip ( )
// l e t p a d e l B e a c h E x p o r t T i p = P a d e l B e a c h E x p o r t T i p ( )
let padelBeachImportTip = PadelBeachImportTip ( )
// l e t p a d e l B e a c h I m p o r t T i p = P a d e l B e a c h I m p o r t T i p ( )
struct InscriptionManagerView : View {
struct InscriptionManagerView : View {
@ -26,11 +26,6 @@ struct InscriptionManagerView: View {
@ EnvironmentObject var networkMonitor : NetworkMonitor
@ EnvironmentObject var networkMonitor : NetworkMonitor
@ Environment ( \ . dismiss ) var dismiss
@ Environment ( \ . dismiss ) var dismiss
@ FetchRequest (
sortDescriptors : [ ] ,
animation : . default )
private var fetchPlayers : FetchedResults < ImportedPlayer >
var tournament : Tournament
var tournament : Tournament
var cancelShouldDismiss : Bool = false
var cancelShouldDismiss : Bool = false
@ -52,14 +47,11 @@ struct InscriptionManagerView: View {
@ State private var contactType : ContactType ? = nil
@ State private var contactType : ContactType ? = nil
@ State private var sentError : ContactManagerError ? = nil
@ State private var sentError : ContactManagerError ? = nil
@ State private var showSubscriptionView : Bool = false
@ State private var showSubscriptionView : Bool = false
@ State private var registrationIssues : Int ? = nil
@ State private var sortedTeams : [ TeamRegistration ] = [ ]
@ State private var walkoutTeams : [ TeamRegistration ] = [ ]
@ State private var unsortedTeamsWithoutWO : [ TeamRegistration ] = [ ]
@ State private var unsortedPlayers : [ PlayerRegistration ] = [ ]
@ State private var teamPaste : URL ?
@ State private var confirmDuplicate : Bool = false
@ State private var confirmDuplicate : Bool = false
@ State private var presentAddTeamView : Bool = false
@ State private var presentAddTeamView : Bool = false
@ State private var compactMode : Bool = false
@ State private var pasteString : String ?
var tournamentStore : TournamentStore {
var tournamentStore : TournamentStore {
return self . tournament . tournamentStore
return self . tournament . tournamentStore
}
}
@ -95,15 +87,21 @@ struct InscriptionManagerView: View {
case all
case all
case walkOut
case walkOut
case waiting
case waiting
case bracket
case groupStage
func localizedLabel ( _ displayStyle : DisplayStyle = . wide ) -> String {
func localizedLabel ( _ displayStyle : DisplayStyle = . wide ) -> String {
switch self {
switch self {
case . all :
case . all :
return displayStyle = = . wide ? " Équipes inscrites / souhaitées " : " Équipes inscrites "
return displayStyle = = . wide ? " Équipes inscrites / souhaitées " : " Paires inscrites "
case . bracket :
return displayStyle = = . wide ? " En Tableau " : " Tableau "
case . groupStage :
return displayStyle = = . wide ? " En Poule " : " Poule "
case . walkOut :
case . walkOut :
return " Forfaits "
return displayStyle = = . wide ? " Forfaits " : " Forfait "
case . waiting :
case . waiting :
return " Liste d'attente "
return displayStyle = = . wide ? " Liste d'attente " : " A ttente "
}
}
}
}
}
}
@ -112,16 +110,7 @@ struct InscriptionManagerView: View {
self . tournament = tournament
self . tournament = tournament
_currentRankSourceDate = State ( wrappedValue : tournament . rankSourceDate )
_currentRankSourceDate = State ( wrappedValue : tournament . rankSourceDate )
}
}
private func _clearScreen ( ) {
teamPaste = nil
unsortedPlayers . removeAll ( )
walkoutTeams . removeAll ( )
unsortedTeamsWithoutWO . removeAll ( )
sortedTeams . removeAll ( )
registrationIssues = nil
}
// F u n c t i o n t o c r e a t e a s i m p l e h a s h f r o m a l i s t o f I D s
// F u n c t i o n t o c r e a t e a s i m p l e h a s h f r o m a l i s t o f I D s
private func _simpleHash ( ids : [ String ] ) -> Int {
private func _simpleHash ( ids : [ String ] ) -> Int {
// C o m b i n e t h e h a s h v a l u e s o f e a c h s t r i n g
// C o m b i n e t h e h a s h v a l u e s o f e a c h s t r i n g
@ -133,7 +122,7 @@ struct InscriptionManagerView: View {
return _simpleHash ( ids : ids1 ) != _simpleHash ( ids : ids2 )
return _simpleHash ( ids : ids1 ) != _simpleHash ( ids : ids2 )
}
}
private func _setHash ( ) async {
private func _setHash ( ) {
#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 {
@ -147,7 +136,7 @@ struct InscriptionManagerView: View {
}
}
}
}
private func _handleHashDiff ( ) async {
private func _handleHashDiff ( ) {
let selectedSortedTeams = tournament . selectedSortedTeams ( )
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 ) {
@ -200,13 +189,10 @@ struct InscriptionManagerView: View {
}
}
}
}
. onAppear {
. onAppear {
_getTeams ( )
_setHash ( )
}
}
. onDisappear {
. onDisappear {
Task {
_handleHashDiff ( )
await _handleHashDiff ( )
}
}
}
. alert ( " Un problème est survenu " , isPresented : messageSentFailed ) {
. alert ( " Un problème est survenu " , isPresented : messageSentFailed ) {
Button ( " OK " ) {
Button ( " OK " ) {
@ -268,7 +254,7 @@ struct InscriptionManagerView: View {
. tint ( . master )
. tint ( . master )
}
}
. sheet ( isPresented : $ presentImportView , onDismiss : {
. sheet ( isPresented : $ presentImportView , onDismiss : {
_getTeams ( )
_setHash ( )
} ) {
} ) {
NavigationStack {
NavigationStack {
FileImportView ( )
FileImportView ( )
@ -276,14 +262,12 @@ struct InscriptionManagerView: View {
. tint ( . master )
. tint ( . master )
}
}
. onChange ( of : tournament . prioritizeClubMembers ) {
. onChange ( of : tournament . prioritizeClubMembers ) {
_clearScreen ( )
_save ( )
_save ( )
_getTeams ( )
_setHash ( )
}
}
. onChange ( of : tournament . teamSorting ) {
. onChange ( of : tournament . teamSorting ) {
_clearScreen ( )
_save ( )
_save ( )
_getTeams ( )
_setHash ( )
}
}
. onChange ( of : currentRankSourceDate ) {
. onChange ( of : currentRankSourceDate ) {
if let currentRankSourceDate , tournament . rankSourceDate != currentRankSourceDate {
if let currentRankSourceDate , tournament . rankSourceDate != currentRankSourceDate {
@ -297,26 +281,36 @@ struct InscriptionManagerView: View {
. tint ( . master )
. tint ( . master )
}
}
. sheet ( isPresented : $ presentAddTeamView , onDismiss : {
. sheet ( isPresented : $ presentAddTeamView , onDismiss : {
editedTeam = nil
_setHash ( )
_getTeams ( )
} ) {
} ) {
NavigationStack {
NavigationStack {
AddTeamView ( tournament : tournament , editedTeam : editedTeam )
AddTeamView ( tournament : tournament )
}
}
. tint ( . master )
. tint ( . master )
}
}
. onChange ( of : filterMode ) {
. sheet ( item : $ editedTeam , onDismiss : {
_prepareTeams ( )
_setHash ( )
}
} ) { editedTeam in
. onChange ( of : sortingMode ) {
NavigationStack {
_prepareTeams ( )
AddTeamView ( tournament : tournament , editedTeam : editedTeam )
}
. tint ( . master )
}
}
. onChange ( of : byDecreasingOrdering ) {
. sheet ( item : $ pasteString , onDismiss : {
_prepareTeams ( )
_setHash ( )
} ) { pasteString in
NavigationStack {
AddTeamView ( tournament : tournament , pasteString : pasteString )
}
. tint ( . master )
}
}
. toolbar {
. toolbar {
ToolbarItemGroup ( placement : . navigationBarTrailing ) {
ToolbarItemGroup ( placement : . navigationBarTrailing ) {
Menu {
Menu {
Toggle ( isOn : $ compactMode ) {
Text ( " Vue compact " )
}
Divider ( )
Picker ( selection : $ filterMode ) {
Picker ( selection : $ filterMode ) {
ForEach ( FilterMode . allCases ) {
ForEach ( FilterMode . allCases ) {
Text ( $0 . localizedLabel ( . short ) ) . tag ( $0 )
Text ( $0 . localizedLabel ( . short ) ) . tag ( $0 )
@ -337,6 +331,7 @@ struct InscriptionManagerView: View {
}
}
} label : {
} label : {
LabelFilter ( )
LabelFilter ( )
. symbolVariant ( filterMode = = . all ? . none : . fill )
}
}
Menu {
Menu {
if tournament . inscriptionClosed ( ) = = false {
if tournament . inscriptionClosed ( ) = = false {
@ -372,7 +367,7 @@ struct InscriptionManagerView: View {
}
}
} else {
} else {
Button {
Button {
tournament . closedRegistrationDate = nil
tournament . unlockRegistration ( )
_save ( )
_save ( )
} label : {
} label : {
Label ( " Ré-ouvrir " , systemImage : " lock.open " )
Label ( " Ré-ouvrir " , systemImage : " lock.open " )
@ -392,43 +387,44 @@ struct InscriptionManagerView: View {
. navigationBarTitleDisplayMode ( . inline )
. navigationBarTitleDisplayMode ( . inline )
}
}
private func _prepareStats ( ) async {
var walkoutTeams : [ TeamRegistration ] {
#if DEBUG_TIME // D E B U G I N G T I M E
tournament . walkoutTeams ( )
let start = Date ( )
defer {
let duration = Duration . milliseconds ( Date ( ) . timeIntervalSince ( start ) * 1_000 )
print ( " func _prepareStats " , duration . formatted ( . units ( allowed : [ . seconds , . milliseconds ] ) ) )
}
#endif
unsortedPlayers = tournament . unsortedPlayers ( )
walkoutTeams = tournament . walkoutTeams ( )
unsortedTeamsWithoutWO = tournament . unsortedTeamsWithoutWO ( )
teamPaste = tournament . pasteDataForImporting ( ) . createTxtFile ( self . tournament . tournamentTitle ( . short ) )
}
}
private func _prepareTeams ( ) {
var unsortedTeamsWithoutWO : [ TeamRegistration ] {
#if DEBUG_TIME // D E B U G I N G T I M E
tournament . unsortedTeamsWithoutWO ( )
let start = Date ( )
}
defer {
let duration = Duration . milliseconds ( Date ( ) . timeIntervalSince ( start ) * 1_000 )
var teamPaste : URL ? {
print ( " func _prepareTeams " , duration . formatted ( . units ( allowed : [ . seconds , . milliseconds ] ) ) )
tournament . pasteDataForImporting ( ) . createTxtFile ( self . tournament . tournamentTitle ( . short ) )
}
}
#endif
var unsortedPlayers : [ PlayerRegistration ] {
tournament . unsortedPlayers ( )
}
var sortedTeams : [ TeamRegistration ] {
if filterMode = = . waiting {
if filterMode = = . waiting {
sortedTeams = tournament . waitingListSortedTeams ( )
return tournament . waitingListSortedTeams ( )
} else {
} else {
sortedTeams = tournament . sortedTeams ( )
return tournament . sortedTeams ( )
}
}
}
}
var filteredTeams : [ TeamRegistration ] {
var filteredTeams : [ TeamRegistration ] {
var teams = sortedTeams
var teams = sortedTeams
if filterMode = = . walkOut {
switch filterMode {
case . walkOut :
teams = teams . filter ( { $0 . walkOut } )
teams = teams . filter ( { $0 . walkOut } )
case . bracket :
teams = teams . filter ( { $0 . inRound ( ) } )
case . groupStage :
teams = teams . filter ( { $0 . inGroupStage ( ) } )
default :
break
}
}
if sortingMode = = . registrationDate {
if sortingMode = = . registrationDate {
teams = teams . sorted ( by : \ . computedRegistrationDate )
teams = teams . sorted ( by : \ . computedRegistrationDate )
}
}
@ -440,53 +436,14 @@ struct InscriptionManagerView: View {
}
}
}
}
private func _getIssues ( ) async {
#if DEBUG_TIME // D E B U G I N G T I M E
let start = Date ( )
defer {
let duration = Duration . milliseconds ( Date ( ) . timeIntervalSince ( start ) * 1_000 )
print ( " func _getIssues " , duration . formatted ( . units ( allowed : [ . seconds , . milliseconds ] ) ) )
}
#endif
await registrationIssues = tournament . registrationIssues ( )
}
private func _getTeams ( ) {
_prepareTeams ( )
Task {
await _prepareStats ( )
await _getIssues ( )
await _setHash ( )
}
}
private func _teamRegisteredView ( ) -> some View {
private func _teamRegisteredView ( ) -> some View {
List {
List {
_informationView ( )
let selectedSortedTeams = tournament . selectedSortedTeams ( )
let selectedSortedTeams = tournament . selectedSortedTeams ( )
if let closedRegistrationDate = tournament . closedRegistrationDate {
Section {
CloseDatePicker ( closedRegistrationDate : closedRegistrationDate )
} footer : {
Text ( " Toutes les équipes ayant été inscrites après la date de clôture seront en liste d'attente. " )
}
if selectedSortedTeams . isEmpty {
Section {
ContentUnavailableView ( " Aucune équipe " , systemImage : " person.2.slash " , description : Text ( " Vous n'avez aucune équipe inscrite avant la date de clôture. " ) )
}
}
}
if presentSearch = = false {
if presentSearch = = false {
_informationView ( )
_rankHandlerView ( )
_rankHandlerView ( )
_relatedTips ( )
_relatedTips ( )
Section {
RowButtonView ( " Compléter la liste " ) {
presentAddTeamView = true
}
}
}
}
let teams = searchField . isEmpty ? filteredTeams : filteredTeams . filter ( { $0 . contains ( searchField . canonicalVersion ) } )
let teams = searchField . isEmpty ? filteredTeams : filteredTeams . filter ( { $0 . contains ( searchField . canonicalVersion ) } )
@ -503,13 +460,7 @@ struct InscriptionManagerView: View {
}
}
RowButtonView ( " Créer une équipe " ) {
RowButtonView ( " Créer une équipe " ) {
// T a s k {
pasteString = searchField
// a w a i t M a i n A c t o r . r u n {
// f e t c h P l a y e r s . n s P r e d i c a t e = S e l f . _ p a s t e P r e d i c a t e ( p a s t e F i e l d : s e a r c h F i e l d , m o s t R e c e n t D a t e : S o u r c e F i l e M a n a g e r . s h a r e d . m o s t R e c e n t D a t e A v a i l a b l e , f i l t e r O p t i o n : _ f i l t e r O p t i o n ( ) )
// f e t c h P l a y e r s . n s S o r t D e s c r i p t o r s = [ N S S o r t D e s c r i p t o r ( k e y P a t h : \ I m p o r t e d P l a y e r . r a n k , a s c e n d i n g : t r u e ) ]
// p a s t e S t r i n g = s e a r c h F i e l d
// }
// }
}
}
RowButtonView ( " D'accord " ) {
RowButtonView ( " D'accord " ) {
@ -518,16 +469,40 @@ struct InscriptionManagerView: View {
}
}
}
}
}
}
ForEach ( teams ) { team in
if compactMode {
let teamIndex = team . index ( in : sortedTeams )
Section {
Section {
TeamDetailView ( team : team )
ForEach ( teams ) { team in
let teamIndex = team . index ( in : sortedTeams )
NavigationLink {
_teamCompactTeamEditionView ( team )
. environment ( tournament )
} label : {
TeamRowView ( team : team )
}
. swipeActions ( edge : . trailing , allowsFullSwipe : true ) {
_teamDeleteButtonView ( team )
}
}
} header : {
} header : {
TeamHeaderView ( team : team , teamIndex : filterMode = = . waiting ? nil : teamIndex , tournament : tournament , teamCount : filterMode = = . waiting ? 0 : selectedSortedTeams . count )
LabeledContent {
} footer : {
Text ( teams . count . formatted ( ) )
_teamFooterView ( team )
} label : {
Text ( " Équipe \( teams . count . pluralSuffix ) " )
}
}
}
. headerProminence ( . increased )
. headerProminence ( . increased )
} else {
ForEach ( teams ) { team in
let teamIndex = team . index ( in : sortedTeams )
Section {
TeamDetailView ( team : team )
} header : {
TeamHeaderView ( team : team , teamIndex : filterMode = = . waiting ? nil : teamIndex , tournament : tournament , teamCount : filterMode = = . waiting ? 0 : selectedSortedTeams . count )
} footer : {
_teamFooterView ( team )
}
. headerProminence ( . increased )
}
}
}
}
}
. searchable ( text : $ searchField , isPresented : $ presentSearch , prompt : Text ( " Chercher parmi les équipes inscrites " ) )
. searchable ( text : $ searchField , isPresented : $ presentSearch , prompt : Text ( " Chercher parmi les équipes inscrites " ) )
@ -535,6 +510,112 @@ struct InscriptionManagerView: View {
. autocorrectionDisabled ( )
. autocorrectionDisabled ( )
}
}
func _teamCompactTeamEditionView ( _ team : TeamRegistration ) -> some View {
List {
Section {
TeamDetailView ( team : team )
} footer : {
FooterButtonView ( " Copier dans le presse-papier " ) {
let pasteboard = UIPasteboard . general
pasteboard . string = team . playersPasteData ( )
}
}
Section {
NavigationLink {
EditingTeamView ( team : team )
. environment ( tournament )
} label : {
Text ( " Éditer une donnée de l'équipe " )
}
NavigationLink {
GroupStageTeamReplacementView ( team : team )
. environment ( tournament )
} label : {
Text ( " Chercher à remplacer " )
}
RowButtonView ( " Modifier la composition de l'équipe " ) {
editedTeam = team
}
}
Section {
Toggle ( isOn : . init ( get : {
return team . wildCardBracket
} , set : { value in
team . resetPositions ( )
team . wildCardGroupStage = false
team . walkOut = false
team . wildCardBracket = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
_setHash ( )
} ) ) {
Text ( " Wildcard Tableau " )
}
Toggle ( isOn : . init ( get : {
return team . wildCardGroupStage
} , set : { value in
team . resetPositions ( )
team . wildCardBracket = false
team . walkOut = false
team . wildCardGroupStage = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
_setHash ( )
} ) ) {
Text ( " Wildcard Poule " )
}
}
Section {
Toggle ( isOn : . init ( get : {
return team . walkOut
} , set : { value in
team . resetPositions ( )
team . wildCardBracket = false
team . wildCardGroupStage = false
team . walkOut = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
_setHash ( )
} ) ) {
Text ( " Forfait " )
}
RowButtonView ( " Effacer l'équipe " , role : . destructive , systemImage : " trash " ) {
team . deleteTeamScores ( )
do {
try tournamentStore . teamRegistrations . delete ( instance : team )
} catch {
Logger . error ( error )
}
_setHash ( )
}
}
}
. toolbar {
ToolbarItem ( placement : . topBarTrailing ) {
MenuWarningView ( tournament : tournament , teams : [ team ] , contactType : $ contactType )
}
}
. toolbarBackground ( . visible , for : . navigationBar )
. navigationTitle ( " Édition de l'équipe " )
. navigationBarTitleDisplayMode ( . inline )
}
@ ViewBuilder
@ ViewBuilder
func rankingDateSourcePickerView ( showDateInLabel : Bool ) -> some View {
func rankingDateSourcePickerView ( showDateInLabel : Bool ) -> some View {
Section {
Section {
@ -597,6 +678,10 @@ struct InscriptionManagerView: View {
switch filterMode {
switch filterMode {
case . all :
case . all :
return unsortedTeamsWithoutWO . count . formatted ( ) + " / " + tournament . teamCount . formatted ( )
return unsortedTeamsWithoutWO . count . formatted ( ) + " / " + tournament . teamCount . formatted ( )
case . bracket :
return tournament . selectedSortedTeams ( ) . filter ( { $0 . inRound ( ) } ) . count . formatted ( )
case . groupStage :
return tournament . selectedSortedTeams ( ) . filter ( { $0 . inGroupStage ( ) } ) . count . formatted ( )
case . walkOut :
case . walkOut :
let wo = walkoutTeams . count . formatted ( )
let wo = walkoutTeams . count . formatted ( )
return wo
return wo
@ -609,30 +694,104 @@ struct InscriptionManagerView: View {
@ ViewBuilder
@ ViewBuilder
private func _informationView ( ) -> some View {
private func _informationView ( ) -> some View {
Section {
Section {
ForEach ( FilterMode . allCases ) { filterMode in
HStack {
LabeledContent {
VStack ( alignment : . leading , spacing : 0 ) {
Text ( _teamCountForFilterMode ( filterMode : filterMode ) )
Text ( " Inscriptions " ) . font ( . caption )
Text ( unsortedTeamsWithoutWO . count . formatted ( ) ) . font ( . largeTitle )
}
. frame ( maxWidth : . infinity )
. contentShape ( Rectangle ( ) )
. onTapGesture {
self . filterMode = . all
}
VStack ( alignment : . leading , spacing : 0 ) {
Text ( " Paires souhaitées " ) . font ( . caption )
Text ( tournament . teamCount . formatted ( ) ) . font ( . largeTitle )
}
. frame ( maxWidth : . infinity )
Button {
presentAddTeamView = true
} label : {
} label : {
Text ( filterMode . localizedLabel ( ) )
Label {
Text ( " Ajouter une équipe " )
} icon : {
Image ( systemName : " person.2.fill " )
. resizable ( )
. scaledToFit ( )
. frame ( height : 44 )
}
. labelStyle ( . iconOnly )
. overlay ( alignment : . bottomTrailing ) {
Image ( systemName : " plus.circle.fill " )
. foregroundColor ( . master )
. background (
Color ( . systemBackground )
. clipShape ( . circle )
)
}
}
}
. buttonBorderShape ( . roundedRectangle )
. buttonStyle ( . borderedProminent )
. frame ( maxWidth : . infinity )
}
}
. fixedSize ( horizontal : false , vertical : false )
. padding ( . horizontal , - 8 )
HStack {
ForEach ( [ FilterMode . waiting , FilterMode . walkOut , FilterMode . groupStage , FilterMode . bracket ] ) { filterMode in
Button {
if self . filterMode = = filterMode {
self . filterMode = . all
} else {
self . filterMode = filterMode
}
} label : {
VStack ( alignment : . leading , spacing : 0 ) {
Text ( filterMode . localizedLabel ( . short ) ) . font ( . caption )
Text ( _teamCountForFilterMode ( filterMode : filterMode ) ) . font ( . largeTitle )
}
. frame ( maxWidth : . infinity )
. contentShape ( Rectangle ( ) )
}
. buttonBorderShape ( . roundedRectangle )
. buttonStyle ( . borderedProminent )
. tint ( self . filterMode = = filterMode ? . master : . beige )
}
}
. foregroundStyle ( . primary )
. fixedSize ( horizontal : false , vertical : false )
NavigationLink {
NavigationLink {
InscriptionInfoView ( )
InscriptionInfoView ( )
. environment ( tournament )
. environment ( tournament )
} label : {
} label : {
LabeledContent {
LabeledContent {
if let registrationIssues {
Text ( tournament . registrationIssues ( ) . formatted ( ) )
Text ( registrationIssues . formatted ( ) )
} else {
ProgressView ( )
}
} label : {
} label : {
Text ( " Problèmes détéctés " )
Text ( " Problèmes détéctés " )
}
}
}
}
if let closedRegistrationDate = tournament . closedRegistrationDate {
CloseDatePicker ( closedRegistrationDate : closedRegistrationDate )
}
} header : {
} header : {
Text ( " Statut des inscriptions " )
HStack {
Spacer ( )
FooterButtonView ( compactMode ? " passer en affichage détaillée " : " passer en affichage compact " ) {
compactMode . toggle ( )
}
Spacer ( )
}
. textCase ( nil )
} footer : {
if tournament . closedRegistrationDate != nil {
Text ( " Toutes les équipes ayant été inscrites après la date de clôture seront en liste d'attente. " )
}
}
}
}
}
//
//
@ -821,119 +980,110 @@ struct InscriptionManagerView: View {
Text ( formattedRegistrationDate )
Text ( formattedRegistrationDate )
}
}
Spacer ( )
Spacer ( )
_teamMenuOptionView ( team )
Menu {
_teamMenuOptionView ( team )
} label : {
LabelOptions ( ) . labelStyle ( . titleOnly )
}
}
}
}
}
@ ViewBuilder
private func _teamMenuOptionView ( _ team : TeamRegistration ) -> some View {
private func _teamMenuOptionView ( _ team : TeamRegistration ) -> some View {
Menu {
Section {
Section {
NavigationLink {
NavigationLink {
GroupStageTeamReplacementView ( team : team )
GroupStageTeamReplacementView ( team : team )
} label : {
} label : {
Text ( " Chercher à remplacer " )
Text ( " Chercher à remplacer " )
}
}
MenuWarningView ( tournament : tournament , teams : [ team ] , contactType : $ contactType )
// D i v i d e r ( )
Button ( " Copier " ) {
let pasteboard = UIPasteboard . general
pasteboard . string = team . playersPasteData ( )
}
// D i v i d e r ( )
Button ( " Changer les joueurs " ) {
editedTeam = team
presentAddTeamView = true
}
Divider ( )
NavigationLink {
EditingTeamView ( team : team )
. environment ( tournament )
} label : {
Text ( " Éditer une donnée de l'équipe " )
}
Divider ( )
Toggle ( isOn : . init ( get : {
return team . wildCardBracket
} , set : { value in
_clearScreen ( )
Task {
MenuWarningView ( tournament : tournament , teams : [ team ] , contactType : $ contactType )
team . resetPositions ( )
// D i v i d e r ( )
team . wildCardGroupStage = false
Button ( " Copier " ) {
team . walkOut = false
let pasteboard = UIPasteboard . general
team . wildCardBracket = value
pasteboard . string = team . playersPasteData ( )
do {
}
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
// D i v i d e r ( )
} catch {
Button ( " Changer les joueurs " ) {
Logger . error ( error )
editedTeam = team
}
}
_getTeams ( )
Divider ( )
}
NavigationLink {
} ) ) {
EditingTeamView ( team : team )
Label ( " Wildcard Tableau " , systemImage : team . wildCardBracket ? " circle.inset.filled " : " circle " )
. environment ( tournament )
} label : {
Text ( " Éditer une donnée de l'équipe " )
}
Divider ( )
Toggle ( isOn : . init ( get : {
return team . wildCardBracket
} , set : { value in
team . resetPositions ( )
team . wildCardGroupStage = false
team . walkOut = false
team . wildCardBracket = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
}
_setHash ( )
} ) ) {
Label ( " Wildcard Tableau " , systemImage : team . wildCardBracket ? " circle.inset.filled " : " circle " )
}
Toggle ( isOn : . init ( get : {
Toggle ( isOn : . init ( get : {
return team . wildCardGroupStage
return team . wildCardGroupStage
} , set : { value in
} , set : { value in
_clearScreen ( )
team . resetPositions ( )
team . wildCardBracket = false
Task {
team . walkOut = false
team . resetPositions ( )
team . wildCardGroupStage = value
team . wildCardBracket = false
do {
team . walkOut = false
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
team . wildCardGroupStage = value
} catch {
do {
Logger . error ( error )
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
_getTeams ( )
}
} ) ) {
Label ( " Wildcard Poule " , systemImage : team . wildCardGroupStage ? " circle.inset.filled " : " circle " )
}
Divider ( )
Toggle ( isOn : . init ( get : {
return team . walkOut
} , set : { value in
_clearScreen ( )
Task {
team . resetPositions ( )
team . wildCardBracket = false
team . wildCardGroupStage = false
team . walkOut = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
_getTeams ( )
}
} ) ) {
Label ( " WO " , systemImage : team . walkOut ? " circle.inset.filled " : " circle " )
}
}
Divider ( )
_setHash ( )
Button ( role : . destructive ) {
} ) ) {
_clearScreen ( )
Label ( " Wildcard Poule " , systemImage : team . wildCardGroupStage ? " circle.inset.filled " : " circle " )
Task {
}
do {
try tournamentStore . teamRegistrations . delete ( instance : team )
Divider ( )
} catch {
Toggle ( isOn : . init ( get : {
Logger . error ( error )
return team . walkOut
}
} , set : { value in
_getTeams ( )
team . resetPositions ( )
}
team . wildCardBracket = false
} label : {
team . wildCardGroupStage = false
LabelDelete ( )
team . walkOut = value
do {
try tournamentStore . teamRegistrations . addOrUpdate ( instance : team )
} catch {
Logger . error ( error )
}
}
_setHash ( )
} ) ) {
Label ( " WO " , systemImage : team . walkOut ? " circle.inset.filled " : " circle " )
}
Divider ( )
_teamDeleteButtonView ( team )
// } h e a d e r : {
// } h e a d e r : {
// T e x t ( t e a m . t e a m L a b e l ( . s h o r t ) )
// T e x t ( t e a m . t e a m L a b e l ( . s h o r t ) )
}
}
private func _teamDeleteButtonView ( _ team : TeamRegistration ) -> some View {
Button ( role : . destructive ) {
team . deleteTeamScores ( )
do {
try tournamentStore . teamRegistrations . delete ( instance : team )
} catch {
Logger . error ( error )
}
}
_setHash ( )
} label : {
} label : {
LabelOptions ( ) . labelStyle ( . titleOnly )
LabelDelete ( )
}
}
}
}