diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index e2a6856..490a368 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -127,6 +127,7 @@ FF1DC55B2BAB80C400FD8220 /* DisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */; }; FF1DF49B2BD8D23900822FA0 /* BarButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DF49A2BD8D23900822FA0 /* BarButtonView.swift */; }; FF1F4B6D2BF9E60B000B4573 /* TournamentBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */; }; + FF1F4B712BF9EFE9000B4573 /* TournamentInscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B702BF9EFE9000B4573 /* TournamentInscriptionView.swift */; }; FF2EFBF02BDE295E0049CE3B /* SendToAllView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF2EFBEF2BDE295E0049CE3B /* SendToAllView.swift */; }; FF3795622B9396D0004EA093 /* PadelClubApp.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FF3795602B9396D0004EA093 /* PadelClubApp.xcdatamodeld */; }; FF3795662B9399AA004EA093 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3795652B9399AA004EA093 /* Persistence.swift */; }; @@ -430,6 +431,7 @@ FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayContext.swift; sourceTree = ""; }; FF1DF49A2BD8D23900822FA0 /* BarButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonView.swift; sourceTree = ""; }; FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBuildView.swift; sourceTree = ""; }; + FF1F4B702BF9EFE9000B4573 /* TournamentInscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentInscriptionView.swift; sourceTree = ""; }; FF2EFBEF2BDE295E0049CE3B /* SendToAllView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendToAllView.swift; sourceTree = ""; }; FF3795612B9396D0004EA093 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = ""; }; FF3795652B9399AA004EA093 /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; @@ -920,6 +922,7 @@ children = ( FF70916B2B91005400AB08DA /* TournamentView.swift */, FF8F26402BADFC8700650388 /* TournamentInitView.swift */, + FF1F4B702BF9EFE9000B4573 /* TournamentInscriptionView.swift */, FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */, FF967CF52BAED51600A9A3BD /* TournamentRunningView.swift */, FF089EBE2BB0B14600F0AEC7 /* FileImportView.swift */, @@ -1663,6 +1666,7 @@ FFC91B012BD85C2F00B29808 /* Court.swift in Sources */, FF967CF82BAEDF0000A9A3BD /* Labels.swift in Sources */, FF089EB42BB0020000F0AEC7 /* PlayerSexPickerView.swift in Sources */, + FF1F4B712BF9EFE9000B4573 /* TournamentInscriptionView.swift in Sources */, FF9267FF2BCE94830080F940 /* CallSettingsView.swift in Sources */, FF025ADD2BD0C94300A86CF8 /* FooterButtonView.swift in Sources */, FF5D0D852BB48997005CB568 /* RankCalculatorView.swift in Sources */, diff --git a/PadelClub/Data/Club.swift b/PadelClub/Data/Club.swift index a6bcc5b..52d33f8 100644 --- a/PadelClub/Data/Club.swift +++ b/PadelClub/Data/Club.swift @@ -35,9 +35,9 @@ class Club : ModelObject, Storable, Hashable { var zipCode: String? var latitude: Double? var longitude: Double? - //var courtCount: Int? + var courtCount: Int = 2 - internal init(creator: String? = nil, name: String, acronym: String? = nil, phone: String? = nil, code: String? = nil, address: String? = nil, city: String? = nil, zipCode: String? = nil, latitude: Double? = nil, longitude: Double? = nil) { + internal init(creator: String? = nil, name: String, acronym: String? = nil, phone: String? = nil, code: String? = nil, address: String? = nil, city: String? = nil, zipCode: String? = nil, latitude: Double? = nil, longitude: Double? = nil, courtCount: Int = 2) { self.creator = creator self.name = name self.acronym = acronym ?? name.acronym() @@ -48,6 +48,7 @@ class Club : ModelObject, Storable, Hashable { self.zipCode = zipCode self.latitude = latitude self.longitude = longitude + self.courtCount = courtCount } func clubTitle(_ displayStyle: DisplayStyle = .wide) -> String { @@ -63,12 +64,12 @@ class Club : ModelObject, Storable, Hashable { return URLs.main.url.appending(path: "?club=\(id)") } - var courts: [Court] { + var customizedCourts: [Court] { Store.main.filter { $0.club == self.id }.sorted(by: \.index) } override func deleteDependencies() throws { - try Store.main.deleteDependencies(items: self.courts) + try Store.main.deleteDependencies(items: self.customizedCourts) } enum CodingKeys: String, CodingKey { @@ -83,6 +84,7 @@ class Club : ModelObject, Storable, Hashable { case _zipCode = "zipCode" case _latitude = "latitude" case _longitude = "longitude" + case _courtCount = "courtCount" } } diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index e208ac0..8a4edf7 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -401,11 +401,13 @@ class Tournament : ModelObject, Storable { if self.isCanceled == true { return .canceled } + + let isBuild = (groupStageCount > 0 && groupStages().isEmpty == false) + || rounds().isEmpty == false - if startDate >= Date() { return .running } + if isBuild && startDate <= Date() { return .running } - if (groupStageCount > 0 && groupStages().isEmpty == false) - || rounds().isEmpty == false { + if isBuild { return .build } return .initial @@ -1415,7 +1417,7 @@ class Tournament : ModelObject, Storable { } func courtNameIfAvailable(atIndex courtIndex: Int) -> String? { - club()?.courts.first(where: { $0.index == courtIndex })?.name + club()?.customizedCourts.first(where: { $0.index == courtIndex })?.name } func courtName(atIndex courtIndex: Int) -> String { diff --git a/PadelClub/Utils/Tips.swift b/PadelClub/Utils/Tips.swift index 236a89a..07e4d32 100644 --- a/PadelClub/Utils/Tips.swift +++ b/PadelClub/Utils/Tips.swift @@ -404,11 +404,11 @@ struct TournamentRunningTip: Tip { } var message: Text? { - return Text("Le tournoi a commencé, les options utiles à sa préparation son accessible ici pour laisser la place aux matchs.") + return Text("Le tournoi a commencé, les options utiles surtout à sa préparation sont maintenant accessibles dans le menu en haut à droite.") } var image: Image? { - Image(systemName: "ellipsis.circle.fill") + Image(systemName: "ellipsis.circle") } } diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index d74f0e0..f9b877b 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -151,8 +151,26 @@ struct ClubDetailView: View { } .disabled(displayContext == .lockedForEditing) } - + + Section { + TournamentFieldsManagerView(localizedStringKey: "Terrains", count: $club.courtCount) + .disabled(displayContext == .lockedForEditing) + .onChange(of: club.courtCount) { + if displayContext != .addition { + do { + try dataStore.clubs.addOrUpdate(instance: club) + } catch { + Logger.error(error) + } + } + } + } footer: { + if displayContext == .lockedForEditing { + Text("Édition impossible, vous n'êtes pas le créateur de ce club.").foregroundStyle(.logoRed) + } + } + if let federalLink = club.federalLink() { Section { LabeledContent("Code Club") { diff --git a/PadelClub/Views/Event/EventCreationView.swift b/PadelClub/Views/Event/EventCreationView.swift index 2a88b9a..ec454e8 100644 --- a/PadelClub/Views/Event/EventCreationView.swift +++ b/PadelClub/Views/Event/EventCreationView.swift @@ -111,7 +111,7 @@ struct EventCreationView: View { } tournaments.forEach { tournament in - tournament.courtCount = selectedClub?.courts.count ?? 2 + tournament.courtCount = selectedClub?.courtCount ?? 2 tournament.startDate = startingDate tournament.dayDuration = duration tournament.setupFederalSettings() diff --git a/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift b/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift index 1c96c50..6e960e3 100644 --- a/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift +++ b/PadelClub/Views/Navigation/Toolbox/ToolboxView.swift @@ -46,7 +46,7 @@ struct ToolboxView: View { } Section { - Link("Guide de la compétition", destination: URLs.padelRules) + Link("Accéder au guide de la compétition", destination: URLs.padelRules.url) } } .navigationTitle(TabDestination.toolbox.title) diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift index 58eda9f..3820956 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift @@ -81,7 +81,7 @@ struct TournamentClubSettingsView: View { @ViewBuilder private func _courtView(atIndex index: Int, tournamentClub: Club) -> some View { - if let court = tournamentClub.courts.first(where: { $0.index == index }) { + if let court = tournamentClub.customizedCourts.first(where: { $0.index == index }) { LabeledContent { FooterButtonView("personnaliser") { selectedCourt = court diff --git a/PadelClub/Views/Tournament/TournamentBuildView.swift b/PadelClub/Views/Tournament/TournamentBuildView.swift index 3506d7a..21c830e 100644 --- a/PadelClub/Views/Tournament/TournamentBuildView.swift +++ b/PadelClub/Views/Tournament/TournamentBuildView.swift @@ -12,8 +12,6 @@ struct TournamentBuildView: View { @ViewBuilder var body: some View { - TournamentInitView(tournament: tournament) - Section { NavigationLink(value: Screen.schedule) { let tournamentStatus = tournament.scheduleStatus() diff --git a/PadelClub/Views/Tournament/TournamentInitView.swift b/PadelClub/Views/Tournament/TournamentInitView.swift index 78584a5..c6342c7 100644 --- a/PadelClub/Views/Tournament/TournamentInitView.swift +++ b/PadelClub/Views/Tournament/TournamentInitView.swift @@ -12,10 +12,17 @@ struct TournamentInitView: View { @ViewBuilder var body: some View { - - if let event = tournament.eventObject() { - let tournaments = event.tournaments - Section { + Section { + NavigationLink(value: Screen.broadcast) { + LabeledContent { + // Text(tournament.isPrivate ? "privée" : "publique") + } label: { + Text("Publication") + } + } + + if let event = tournament.eventObject() { + let tournaments = event.tournaments NavigationLink(value: Screen.event) { LabeledContent { Text(tournaments.count.formatted() + " épreuve" + tournaments.count.pluralSuffix) @@ -24,9 +31,6 @@ struct TournamentInitView: View { } } } - } - - Section { NavigationLink(value: Screen.settings) { LabeledContent { Text(tournament.settingsDescriptionLocalizedLabel()) @@ -38,29 +42,6 @@ struct TournamentInitView: View { } footer: { Text("La date, la catégorie, le niveau, le nombre de terrain, les formats, etc.") } - - Section { - NavigationLink(value: Screen.broadcast) { - LabeledContent { -// Text(tournament.isPrivate ? "privée" : "publique") - } label: { - Text("Publication") - } - } - } - - Section { - NavigationLink(value: Screen.structure) { - LabeledContent { - Text(tournament.structureDescriptionLocalizedLabel()) - .tint(.master) - } label: { - LabelStructure() - } - } - } footer: { - Text("Nombre d'équipes, de poules, de qualifiés sortant, etc.") - } } } diff --git a/PadelClub/Views/Tournament/TournamentInscriptionView.swift b/PadelClub/Views/Tournament/TournamentInscriptionView.swift new file mode 100644 index 0000000..9d55c77 --- /dev/null +++ b/PadelClub/Views/Tournament/TournamentInscriptionView.swift @@ -0,0 +1,70 @@ +// +// TournamentInscriptionView.swift +// PadelClub +// +// Created by Razmig Sarkissian on 19/05/2024. +// + +import SwiftUI +import LeStorage + +struct TournamentInscriptionView: View { + @EnvironmentObject var dataStore: DataStore + var tournament: Tournament + + @ViewBuilder + var body: some View { + Section { + NavigationLink(value: Screen.inscription) { + LabeledContent { + Text(tournament.unsortedTeams().count.formatted() + "/" + tournament.teamCount.formatted()) + } label: { + Text("Gestion des inscriptions") + if let closedRegistrationDate = tournament.closedRegistrationDate { + Text("clôturé le " + closedRegistrationDate.formatted(date: .abbreviated, time: .shortened)) + } + } + } + if let endOfInscriptionDate = tournament.mandatoryRegistrationCloseDate(), tournament.inscriptionClosed() == false && tournament.hasStarted() == false { + LabeledContent { + Text(endOfInscriptionDate.formatted(date: .abbreviated, time: .shortened)) + } label: { + Text("Date limite") + } + } + + if tournament.state() != .running { + NavigationLink(value: Screen.structure) { + LabeledContent { + Text(tournament.structureDescriptionLocalizedLabel()) + .tint(.master) + } label: { + LabelStructure() + } + } + } + } footer: { + if tournament.inscriptionClosed() == false && tournament.state() == .build && tournament.unsortedTeams().isEmpty == false && tournament.hasStarted() == false { + Button { + tournament.lockRegistration() + _save() + } label: { + Text("clôturer les inscriptions") + .underline() + } + .buttonStyle(.borderless) + } else if tournament.state() != .running { + Text("Nombre d'équipes, de poules, de qualifiés sortant, etc.") + } + } + } + + private func _save() { + do { + try dataStore.tournaments.addOrUpdate(instance: tournament) + } catch { + Logger.error(error) + } + } + +} diff --git a/PadelClub/Views/Tournament/TournamentRunningView.swift b/PadelClub/Views/Tournament/TournamentRunningView.swift index 5ebd72d..f0e4ec1 100644 --- a/PadelClub/Views/Tournament/TournamentRunningView.swift +++ b/PadelClub/Views/Tournament/TournamentRunningView.swift @@ -17,9 +17,7 @@ struct TournamentRunningView: View { } @ViewBuilder - var body: some View { - TournamentBuildView(tournament: tournament) - + var body: some View { MatchListView(section: "en cours", matches: tournament.runningMatches(allMatches)) MatchListView(section: "à lancer", matches: tournament.readyMatches(allMatches), isExpanded: false) MatchListView(section: "disponible", matches: tournament.availableToStart(allMatches), isExpanded: false) diff --git a/PadelClub/Views/Tournament/TournamentView.swift b/PadelClub/Views/Tournament/TournamentView.swift index 86c4bda..4543732 100644 --- a/PadelClub/Views/Tournament/TournamentView.swift +++ b/PadelClub/Views/Tournament/TournamentView.swift @@ -39,41 +39,11 @@ struct TournamentView: View { var body: some View { VStack(spacing: 0.0) { List { - SubscriptionInfoView() - - if tournament.state() != .canceled { - Section { - NavigationLink(value: Screen.inscription) { - LabeledContent { - Text(tournament.unsortedTeams().count.formatted() + "/" + tournament.teamCount.formatted()) - } label: { - Text("Gestion des inscriptions") - if let closedRegistrationDate = tournament.closedRegistrationDate { - Text("clôturé le " + closedRegistrationDate.formatted(date: .abbreviated, time: .shortened)) - } - } - } - if let endOfInscriptionDate = tournament.mandatoryRegistrationCloseDate(), tournament.inscriptionClosed() == false && tournament.hasStarted() == false { - LabeledContent { - Text(endOfInscriptionDate.formatted(date: .abbreviated, time: .shortened)) - } label: { - Text("Date limite") - } - } - } footer: { - if tournament.inscriptionClosed() == false && tournament.state() == .build && tournament.unsortedTeams().isEmpty == false && tournament.hasStarted() == false { - Button { - tournament.lockRegistration() - _save() - } label: { - Text("clôturer les inscriptions") - .underline() - } - .buttonStyle(.borderless) - } - } - } + TipView(tournamentRunningTip) + .tipStyle(tint: nil) + SubscriptionInfoView() + switch tournament.state() { case .canceled: Section { @@ -85,17 +55,23 @@ struct TournamentView: View { Text("todo expliquer cet état") } case .initial: + TournamentInscriptionView(tournament: tournament) TournamentInitView(tournament: tournament) case .build: + TournamentInscriptionView(tournament: tournament) + TournamentInitView(tournament: tournament) TournamentBuildView(tournament: tournament) case .running: - TournamentRunningView(tournament: tournament) - + TournamentInscriptionView(tournament: tournament) + TournamentBuildView(tournament: tournament) if tournament.hasEnded() { - NavigationLink(value: Screen.rankings) { - Text("Classement") + Section { + NavigationLink(value: Screen.rankings) { + Text("Classement") + } } } + TournamentRunningView(tournament: tournament) } } } @@ -189,14 +165,11 @@ struct TournamentView: View { } label: { LabelOptions() } - .popoverTip(tournamentRunningTip) - .onAppear { - TournamentRunningTip.isRunning = tournament.state == .running - } } } } .onAppear { + TournamentRunningTip.isRunning = tournament.state() == .running Logger.log("Payment = \(String(describing: self.tournament.payment)), canceled = \(self.tournament.isCanceled)") } }