diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 7d15d0c..55692ae 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -248,8 +248,6 @@ FFCFC01A2BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC0192BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift */; }; FFCFC01C2BBC5AAA00B82851 /* SetDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */; }; FFD783FF2B91BA42000F62A6 /* PadelClubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */; }; - FFD784022B91C1B4000F62A6 /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD784012B91C1B4000F62A6 /* WelcomeView.swift */; }; - FFD784042B91C280000F62A6 /* EmptyActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD784032B91C280000F62A6 /* EmptyActivityView.swift */; }; FFDB1C6D2BB2A02000F1E467 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */; }; FFDB1C732BB2CFE900F1E467 /* MySortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */; }; FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */; }; @@ -546,8 +544,6 @@ FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDescriptor.swift; sourceTree = ""; }; FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadelClubView.swift; sourceTree = ""; }; FFD784002B91BF79000F62A6 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; - FFD784012B91C1B4000F62A6 /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = ""; }; - FFD784032B91C280000F62A6 /* EmptyActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyActivityView.swift; sourceTree = ""; }; FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySortDescriptor.swift; sourceTree = ""; }; FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredViewModifier.swift; sourceTree = ""; }; @@ -936,8 +932,6 @@ FF3F74F92B91A018004CFE0E /* Screen */ = { isa = PBXGroup; children = ( - FF6EC8FD2B94792300EA7F5A /* Screen.swift */, - FF6EC8FF2B94794700EA7F5A /* PresentationContext.swift */, FF70916D2B9108C600AB08DA /* InscriptionManagerView.swift */, FF8F26422BADFE5B00650388 /* TournamentSettingsView.swift */, FF8F26532BAE1E4400650388 /* TableStructureView.swift */, @@ -984,6 +978,8 @@ FF3F74FD2B91A087004CFE0E /* ViewModel */ = { isa = PBXGroup; children = ( + FF6EC8FD2B94792300EA7F5A /* Screen.swift */, + FF6EC8FF2B94794700EA7F5A /* PresentationContext.swift */, FF7091652B90F0B000AB08DA /* TabDestination.swift */, FF025AEC2BD1513700A86CF8 /* AppScreen.swift */, FF3F74FE2B91A2D4004CFE0E /* AgendaDestination.swift */, @@ -1176,8 +1172,6 @@ isa = PBXGroup; children = ( FF82CFC82B9132AF00B0CAF2 /* ActivityView.swift */, - FFD784032B91C280000F62A6 /* EmptyActivityView.swift */, - FFD784012B91C1B4000F62A6 /* WelcomeView.swift */, FF59FFB22B90EFAC0061EFF9 /* EventListView.swift */, FF5D0D8A2BB4D1E3005CB568 /* CalendarView.swift */, ); @@ -1596,7 +1590,6 @@ FF9AC3952BE3627B00C2E883 /* GroupStageTeamReplacementView.swift in Sources */, FF4C7F022BBBD7150031B6A3 /* TabItemModifier.swift in Sources */, FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */, - FFD784042B91C280000F62A6 /* EmptyActivityView.swift in Sources */, FF0E0B6D2BC254C6005F00A9 /* TournamentScheduleView.swift in Sources */, FF025AF12BD1AEBD00A86CF8 /* MatchFormatStorageView.swift in Sources */, FF3F74F62B919E45004CFE0E /* UmpireView.swift in Sources */, @@ -1618,7 +1611,6 @@ FFF964532BC262B000EEF017 /* PlanningSettingsView.swift in Sources */, FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */, FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */, - FFD784022B91C1B4000F62A6 /* WelcomeView.swift in Sources */, FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */, FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */, FF967D032BAEF0C000A9A3BD /* MatchDetailView.swift in Sources */, diff --git a/PadelClub/Data/DataStore.swift b/PadelClub/Data/DataStore.swift index 4109db9..4a8f346 100644 --- a/PadelClub/Data/DataStore.swift +++ b/PadelClub/Data/DataStore.swift @@ -105,7 +105,7 @@ class DataStore: ObservableObject { if let _ = Guard.main.currentPlan { return .creation } - if let user = self.user, user.club != nil { + if let user = self.user, user.clubs != nil { if user.umpireCode != nil { return .creation } else { diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index 34f6d95..b3b99dc 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -24,7 +24,7 @@ class User: UserBase, Storable { public var id: String = Store.randomId() public var username: String public var email: String - var club: String? + var clubs: [String]? var umpireCode: String? var licenceId: String? var firstName: String @@ -61,7 +61,7 @@ class User: UserBase, Storable { case _id = "id" case _username = "username" case _email = "email" - case _club = "club" + case _clubs = "clubs" case _umpireCode = "umpireCode" case _licenceId = "licenceId" case _firstName = "firstName" diff --git a/PadelClub/Utils/LocationManager.swift b/PadelClub/Utils/LocationManager.swift index 660f095..50afc59 100644 --- a/PadelClub/Utils/LocationManager.swift +++ b/PadelClub/Utils/LocationManager.swift @@ -17,7 +17,6 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { @Published var requestStarted: Bool = false @Published var userReadableCityOrZipcode: String = "" @Published var lastError: Error? = nil - var shouldRequestLocation: Bool = false override init() { super.init() @@ -41,10 +40,8 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { if manager.authorizationStatus == .authorizedWhenInUse || manager.authorizationStatus == .authorizedAlways { - if requestStarted == false && shouldRequestLocation { - DispatchQueue.main.async { - self.requestLocation() - } + DispatchQueue.main.async { + self.requestLocation() } } } diff --git a/PadelClub/Views/Tournament/Screen/PresentationContext.swift b/PadelClub/ViewModel/PresentationContext.swift similarity index 100% rename from PadelClub/Views/Tournament/Screen/PresentationContext.swift rename to PadelClub/ViewModel/PresentationContext.swift diff --git a/PadelClub/Views/Tournament/Screen/Screen.swift b/PadelClub/ViewModel/Screen.swift similarity index 100% rename from PadelClub/Views/Tournament/Screen/Screen.swift rename to PadelClub/ViewModel/Screen.swift diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index ed77f5b..9a0b310 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -6,6 +6,7 @@ // import SwiftUI +import LeStorage struct ClubDetailView: View { @Bindable var club: Club @@ -138,6 +139,20 @@ struct ClubDetailView: View { .navigationBarTitleDisplayMode(.inline) .toolbar(.visible, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button { + do { + dataStore.user?.clubs?.removeAll(where: { $0.id == club.id }) + try dataStore.userStorage.update() + } catch { + Logger.error(error) + } + } label: { + LabelDelete() + } + } + } .onDisappear { if displayContext == .edition { try? dataStore.clubs.addOrUpdate(instance: club) diff --git a/PadelClub/Views/Club/ClubSearchView.swift b/PadelClub/Views/Club/ClubSearchView.swift index f753c68..b80e524 100644 --- a/PadelClub/Views/Club/ClubSearchView.swift +++ b/PadelClub/Views/Club/ClubSearchView.swift @@ -25,6 +25,8 @@ struct ClubSearchView: View { @State private var getForwardCityList: [CLPlacemark] = [] @State private var searchPresented: Bool = false @State private var showingSettingsAlert = false + @State private var presentClubCreationView: Bool = false + var displayContext: DisplayContext = .edition var club: Club? @@ -141,7 +143,7 @@ struct ClubSearchView: View { if searchAttempted { Label("Aucun club trouvé", systemImage: "mappin.slash") } else { - Text("Recherche de club") + Label("Recherche de club", systemImage: "location.circle") } } description: { Text("Padel Club peut rechercher un club autour de vous, d'une ville ou d'un code postal, facilitant ainsi la saisie d'information.") @@ -160,12 +162,22 @@ struct ClubSearchView: View { RowButtonView("Chercher une ville ou un code postal") { searchPresented = true } + + if searchAttempted { + RowButtonView("Créer un club manuellement") { + presentClubCreationView = true + } + } } } } else { ContentUnavailableView("recherche en cours", systemImage: "mappin.and.ellipse", description: Text("recherche des clubs autour de vous")) } } + .sheet(isPresented: $presentClubCreationView) { + CreateClubView() + .tint(.master) + } .alert(isPresented: $showingSettingsAlert) { Alert( title: Text("Réglages"), diff --git a/PadelClub/Views/Navigation/Agenda/ActivityView.swift b/PadelClub/Views/Navigation/Agenda/ActivityView.swift index 90c2cee..55ef80d 100644 --- a/PadelClub/Views/Navigation/Agenda/ActivityView.swift +++ b/PadelClub/Views/Navigation/Agenda/ActivityView.swift @@ -20,7 +20,8 @@ struct ActivityView: View { @State private var isGatheringFederalTournaments: Bool = false @State private var error: Error? @State private var uuid: UUID = UUID() - + @State private var presentClubSearchView: Bool = false + var runningTournaments: [FederalTournamentHolder] { dataStore.tournaments.filter({ $0.endDate == nil }) .filter({ federalDataViewModel.isTournamentValidForFilters($0) }) @@ -199,6 +200,10 @@ struct ActivityView: View { .environment(navigation) .tint(.master) } + .sheet(isPresented: $presentClubSearchView) { + ClubImportView() + .tint(.master) + } } } } @@ -245,8 +250,14 @@ struct ActivityView: View { RowButtonView("Créer un nouvel événement") { newTournament = Tournament.newEmptyInstance() } - RowButtonView("Importer via Tenup") { - navigation.agendaDestination = .tenup + if dataStore.clubs.isEmpty { + RowButtonView("Chercher l'un de vos clubs") { + presentClubSearchView = true + } + } else { + RowButtonView("Importer via Tenup") { + navigation.agendaDestination = .tenup + } } } } @@ -264,9 +275,9 @@ struct ActivityView: View { ContentUnavailableView { Label("Aucun tournoi", systemImage: "shield.slash") } description: { - Text("Pour voir vos tournois tenup ici, indiquez vos clubs préférés.") + Text("Pour voir vos tournois tenup ici, choisissez vos clubs.") } actions: { - RowButtonView("Choisir mes clubs préférés") { + RowButtonView("Choisir mes clubs") { navigation.selectedTab = .umpire } } diff --git a/PadelClub/Views/Navigation/Agenda/EmptyActivityView.swift b/PadelClub/Views/Navigation/Agenda/EmptyActivityView.swift deleted file mode 100644 index bd0af4f..0000000 --- a/PadelClub/Views/Navigation/Agenda/EmptyActivityView.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// EmptyActivityView.swift -// PadelClub -// -// Created by Razmig Sarkissian on 01/03/2024. -// - -import SwiftUI - -struct EmptyActivityView: View { - @State private var newTournament: Tournament? - - var body: some View { - NavigationStack { - List { - WelcomeView() - - Section { - RowButtonView("Créer votre premier événement", action: { - newTournament = Tournament.newEmptyInstance() - }) - } - - Section { - RowButtonView("Importer vos tournois Tenup", action: { - - }) - } - } - .sheet(item: $newTournament) { tournament in - EventCreationView(tournaments: [tournament]) - .tint(.master) - } - } - } -} - -#Preview { - EmptyActivityView() -} diff --git a/PadelClub/Views/Navigation/Agenda/WelcomeView.swift b/PadelClub/Views/Navigation/Agenda/WelcomeView.swift deleted file mode 100644 index f7763b7..0000000 --- a/PadelClub/Views/Navigation/Agenda/WelcomeView.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// WelcomeView.swift -// PadelClub -// -// Created by Razmig Sarkissian on 01/03/2024. -// - -import SwiftUI - -struct WelcomeView: View { - var body: some View { - Image(.padelClubLogoFondfonce) - .resizable() - .scaledToFit() - .buttonStyle(.borderedProminent) - .tint(.logoBackground) - .listRowBackground(Color.clear) - .listRowInsets(EdgeInsets(.zero)) - } -} - -#Preview { - WelcomeView() -} diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index 94768e7..6a4920a 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -101,7 +101,7 @@ struct MainView: View { checkingFiles = false if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast { - _startImporting() + //_startImporting() } } diff --git a/PadelClub/Views/Navigation/PadelClubView.swift b/PadelClub/Views/Navigation/PadelClubView.swift index 7c74e05..5f81c40 100644 --- a/PadelClub/Views/Navigation/PadelClubView.swift +++ b/PadelClub/Views/Navigation/PadelClubView.swift @@ -11,8 +11,8 @@ import SwiftData struct PadelClubView: View { @State private var checkingFilesAttempt: Int = 0 @State private var checkingFiles: Bool = false - @State private var importingFiles: Bool = false - + @AppStorage("importingFiles") var importingFiles: Bool = false + @EnvironmentObject var dataStore: DataStore var lastDataSource: String? { @@ -72,18 +72,20 @@ struct PadelClubView: View { Text(monthData.monthKey) } } -// -// if players.isEmpty { -// ContentUnavailableView { -// Label("Aucun joueur importé", systemImage: "person.slash") -// } description: { -// Text("Padel peut importer toutes les données publique de la FFT concernant tous les compétiteurs et compétitrices.") -// } actions: { -// RowButtonView("Démarrer l'importation") { -// _startImporting() -// } -// } -// } + + if importingFiles { + ContentUnavailableView("Importation en cours", systemImage: "server.rack", description: Text("Une importation des données fédérales publiques est en cours, veuillez patienter.")) + } else if (players.isEmpty || lastDataSource == nil) { + ContentUnavailableView { + Label("Aucun joueur importé", systemImage: "person.slash") + } description: { + Text("Padel Club peut importer toutes les données publiques de la FFT concernant tous les compétiteurs et compétitrices.") + } actions: { + RowButtonView("Démarrer l'importation") { + _startImporting() + } + } + } } .task { await self._checkSourceFileAvailability() diff --git a/PadelClub/Views/Navigation/Umpire/UmpireView.swift b/PadelClub/Views/Navigation/Umpire/UmpireView.swift index ad416cf..37bddc4 100644 --- a/PadelClub/Views/Navigation/Umpire/UmpireView.swift +++ b/PadelClub/Views/Navigation/Umpire/UmpireView.swift @@ -59,7 +59,11 @@ struct UmpireView: View { user.licenceId = player.license let club = dataStore.clubs.first(where: { $0.code == player.clubCode }) ?? Club(name: player.clubName!, code: player.clubCode!) try? dataStore.clubs.addOrUpdate(instance: club) - user.club = club.id + if user.clubs == nil { + user.clubs = [club.id] + } else { + user.clubs!.insert(club.id, at: 0) + } dataStore.setUser(user) } }) @@ -82,22 +86,19 @@ struct UmpireView: View { } } - if let clubId = user.club { - if let club = dataStore.clubs.findById(clubId) { - Section { - NavigationLink { - ClubDetailView(club: club, displayContext: .edition) - } label: { - ClubRowView(club: club) - } - } header: { - Text("Mon club") - } footer: { - Button("supprimer", role: .destructive) { - user.club = nil - dataStore.setUser(user) + if let clubs = user.clubs { + Section { + ForEach(clubs) { clubId in + if let club = dataStore.clubs.findById(clubId) { + NavigationLink { + ClubDetailView(club: club, displayContext: .edition) + } label: { + ClubRowView(club: club) + } } } + } header: { + Text("Mes clubs") } } } @@ -109,7 +110,7 @@ struct UmpireView: View { LabeledContent { Text(dataStore.clubs.count.formatted()) } label: { - Label("Mes clubs favoris", systemImage: "house.and.flag.circle.fill") + Label("Mes clubs", systemImage: "house.and.flag.circle.fill") } } }