diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 649c58c..cde1d14 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1908,7 +1908,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 66; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; @@ -1949,7 +1949,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 66; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; diff --git a/PadelClub/Data/Club.swift b/PadelClub/Data/Club.swift index ac70af8..53a3661 100644 --- a/PadelClub/Data/Club.swift +++ b/PadelClub/Data/Club.swift @@ -170,7 +170,7 @@ class Club : ModelObject, Storable, Hashable { extension Club { var isValid: Bool { - name.isEmpty == false && acronym.isEmpty == false + name.isEmpty == false && name.count > 3 } func automaticShortName() -> String { @@ -216,7 +216,7 @@ extension Club { } func hasBeenCreated(by creatorId: String?) -> Bool { - return creatorId == creator + return creatorId == creator || creator == nil } func isFavorite() -> Bool { @@ -235,7 +235,7 @@ extension Club { if clubs.isEmpty == false { return clubs.first! } else { - return Club(name: name, code: code, city: city, zipCode: zipCode) + return Club(creator: Store.main.userId, name: name, code: code, city: city, zipCode: zipCode) } } diff --git a/PadelClub/Data/Federal/FederalTournament.swift b/PadelClub/Data/Federal/FederalTournament.swift index 4d142cb..939ef01 100644 --- a/PadelClub/Data/Federal/FederalTournament.swift +++ b/PadelClub/Data/Federal/FederalTournament.swift @@ -20,7 +20,7 @@ struct FederalTournament: Identifiable, Codable { let club = DataStore.shared.user.clubsObjects().first(where: { $0.code == codeClub }) var event = DataStore.shared.events.first(where: { $0.tenupId == id.string }) if event == nil { - event = Event(creator: DataStore.shared.user.id, club: club?.id, name: libelle, tenupId: id.string) + event = Event(creator: Store.main.userId, club: club?.id, name: libelle, tenupId: id.string) do { try DataStore.shared.events.addOrUpdate(instance: event!) } catch { diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index b7729f0..7fa5218 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -166,6 +166,11 @@ class GroupStage: ModelObject, Storable { return _matches().filter { matchIndexes.contains($0.index) } } + func initialStartDate(forTeam team: TeamRegistration) -> Date? { + guard let groupStagePosition = team.groupStagePosition else { return nil } + return matches(forGroupStagePosition: groupStagePosition).compactMap({ $0.startDate }).sorted().first ?? startDate + } + func matchPlayed(by groupStagePosition: Int, againstPosition: Int) -> Match? { if groupStagePosition == againstPosition { return nil } let combos = Array((0.. Date { - let computedGroupStageChunkCount = groupStageChunkCount ?? 1 + let computedGroupStageChunkCount = groupStageChunkCount ?? tournament.getGroupStageChunkValue() let groupStages: [GroupStage] = tournament.groupStages() let numberOfCourtsAvailablePerRotation: Int = tournament.courtCount @@ -677,7 +677,10 @@ class MatchScheduler : ModelObject, Storable { } func updateSchedule(tournament: Tournament) -> Bool { - let lastDate = updateGroupStageSchedule(tournament: tournament) + var lastDate = tournament.startDate + if tournament.groupStageCount > 0 { + lastDate = updateGroupStageSchedule(tournament: tournament) + } return updateBracketSchedule(tournament: tournament, fromRoundId: nil, fromMatchId: nil, startDate: lastDate) } } diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 2ae020f..d2fac20 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1762,7 +1762,7 @@ class Tournament : ModelObject, Storable { } func getGroupStageChunkValue() -> Int { - if teamsPerGroupStage >= 2 { + if groupStageCount > 0 && teamsPerGroupStage >= 2 { let result = courtCount / (teamsPerGroupStage / 2) let remainder = courtCount % (teamsPerGroupStage / 2) let value = remainder == 0 ? result : result + 1 diff --git a/PadelClub/Views/Calling/GroupStageCallingView.swift b/PadelClub/Views/Calling/GroupStageCallingView.swift index a26d723..396b586 100644 --- a/PadelClub/Views/Calling/GroupStageCallingView.swift +++ b/PadelClub/Views/Calling/GroupStageCallingView.swift @@ -70,8 +70,8 @@ struct GroupStageCallingView: View { private func _groupStageView(groupStage: GroupStage) -> some View { let teams = groupStage.teams() List { - if let startDate = groupStage.startDate { - ForEach(teams) { team in + ForEach(teams) { team in + if let startDate = groupStage.initialStartDate(forTeam: team) { Section { CallView.TeamView(team: team) } header: { @@ -80,7 +80,6 @@ struct GroupStageCallingView: View { CallView(teams: [team], callDate: startDate, matchFormat: groupStage.matchFormat, roundLabel: "poule") } } - } } .overlay { diff --git a/PadelClub/Views/Cashier/Event/EventCreationView.swift b/PadelClub/Views/Cashier/Event/EventCreationView.swift index 2bff9f6..2baf2bd 100644 --- a/PadelClub/Views/Cashier/Event/EventCreationView.swift +++ b/PadelClub/Views/Cashier/Event/EventCreationView.swift @@ -130,10 +130,6 @@ struct EventCreationView: View { private func _validate() { let event = Event(creator: Store.main.userId, name: eventName) - event.club = selectedClub?.id - tournaments.forEach { tournament in - tournament.event = event.id - } do { try dataStore.events.addOrUpdate(instance: event) @@ -142,6 +138,7 @@ struct EventCreationView: View { } tournaments.forEach { tournament in + tournament.event = event.id tournament.courtCount = selectedClub?.courtCount ?? 2 tournament.startDate = startingDate tournament.dayDuration = duration @@ -154,6 +151,17 @@ struct EventCreationView: View { Logger.error(error) } + + if let selectedClub, let verifiedSelectedClubId = dataStore.clubs.first(where: { selectedClub.id == $0.id })?.id { + event.club = verifiedSelectedClubId + do { + try dataStore.events.addOrUpdate(instance: event) + } catch { + Logger.error(error) + } + } + + dismiss() navigation.path.append(tournaments.first!) } diff --git a/PadelClub/Views/Club/ClubDetailView.swift b/PadelClub/Views/Club/ClubDetailView.swift index 924e8df..91e95cb 100644 --- a/PadelClub/Views/Club/ClubDetailView.swift +++ b/PadelClub/Views/Club/ClubDetailView.swift @@ -43,6 +43,7 @@ struct ClubDetailView: View { dataStore.user.clubs.append(club.id) } self.dataStore.saveUser() + dismiss() } } footer: { if displayContext == .lockedForEditing { @@ -52,7 +53,7 @@ struct ClubDetailView: View { } Section { - TextField("Nom du club", text: $club.name) + TextField("Nom du club (4 lettres mini)", text: $club.name) .autocorrectionDisabled() .keyboardType(.alphabet) .frame(maxWidth: .infinity) @@ -186,31 +187,6 @@ struct ClubDetailView: View { } } - if displayContext == .addition { - Section { - } header: { - HStack { - VStack { - Divider() - } - Text("ou") - VStack { - Divider() - } - } - } - - Section { - NavigationLink { - ClubSearchView(displayContext: .edition, club: club) - } label: { - Label("Chercher dans la base fédérale", systemImage: "magnifyingglass") - } - } footer: { - Text("Vous pouvez chercher un club dans la base fédérale et importer les informations directement.") - } - } - ClubCourtSetupView(club: club, displayContext: displayContext, selectedCourt: $selectedCourt, hideLockForEditingMessage: true) if displayContext == .edition { diff --git a/PadelClub/Views/Club/ClubRowView.swift b/PadelClub/Views/Club/ClubRowView.swift index 7ba1656..1c087f2 100644 --- a/PadelClub/Views/Club/ClubRowView.swift +++ b/PadelClub/Views/Club/ClubRowView.swift @@ -19,7 +19,12 @@ struct ClubRowView: View { // .foregroundStyle(club.isFavorite() ? .green : .logoRed) // } } label: { - Text(club.name) + HStack { + Text(club.name) + Spacer() + } + .frame(maxWidth: .infinity) + .contentShape(Rectangle()) } } } diff --git a/PadelClub/Views/Club/ClubSearchView.swift b/PadelClub/Views/Club/ClubSearchView.swift index 6ea6d9f..beea497 100644 --- a/PadelClub/Views/Club/ClubSearchView.swift +++ b/PadelClub/Views/Club/ClubSearchView.swift @@ -303,7 +303,7 @@ struct ClubSearchView: View { } private func _importClub(clubToEdit: Club, clubMarker: ClubMarker) { - if clubToEdit.creator == dataStore.user.id { + if clubToEdit.hasBeenCreated(by: Store.main.userId) { if clubToEdit.name.isEmpty { clubToEdit.name = clubMarker.nom.capitalized clubToEdit.acronym = clubToEdit.automaticShortName().capitalized @@ -314,17 +314,19 @@ struct ClubSearchView: View { clubToEdit.city = clubMarker.ville } - if displayContext == .addition { + if displayContext == .addition && clubToEdit.hasBeenCreated(by: Store.main.userId) { do { try dataStore.clubs.addOrUpdate(instance: clubToEdit) - if dataStore.user.clubs.contains(where: { $0 == clubToEdit.id }) == false { - dataStore.user.clubs.append(clubToEdit.id) - self.dataStore.saveUser() - } } catch { Logger.error(error) } } + + if dataStore.user.clubs.contains(where: { $0 == clubToEdit.id }) == false { + dataStore.user.clubs.append(clubToEdit.id) + self.dataStore.saveUser() + } + dismiss() selection?(clubToEdit) } diff --git a/PadelClub/Views/Club/ClubsView.swift b/PadelClub/Views/Club/ClubsView.swift index 9812223..913d8f7 100644 --- a/PadelClub/Views/Club/ClubsView.swift +++ b/PadelClub/Views/Club/ClubsView.swift @@ -27,6 +27,20 @@ struct ClubsView: View { var body: some View { List { + #if DEBUG + Section { + RowButtonView("Delete unexisted clubs", action: { + var ids = dataStore.user.clubs + ids.forEach { clubId in + if dataStore.clubs.findById(clubId) == nil { + dataStore.user.clubs.removeAll(where: { $0 == clubId }) + } + } + dataStore.saveUser() + }) + } + #endif + let clubs : [Club] = dataStore.user.clubsObjects(includeCreated: false) let onlyCreatedClubs : [Club] = dataStore.user.createdClubsObjectsNotFavorite() diff --git a/PadelClub/Views/Club/CreateClubView.swift b/PadelClub/Views/Club/CreateClubView.swift index 3adfd47..235c448 100644 --- a/PadelClub/Views/Club/CreateClubView.swift +++ b/PadelClub/Views/Club/CreateClubView.swift @@ -30,6 +30,10 @@ struct CreateClubView: View { ProgressView() } else { ButtonValidateView { + if club.acronym.isEmpty { + club.acronym = club.name.canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines).acronym() + } + validationInProgress = true } .disabled(club.isValid == false) @@ -45,27 +49,25 @@ struct CreateClubView: View { Logger.error(error) } - let club = Club.findOrCreate(name: club.name, code: club.code, city: club.city, zipCode: club.zipCode) - club.creator = Store.main.userId + let newClub = Club.findOrCreate(name: club.name, code: club.code, city: club.city, zipCode: club.zipCode) //update existing club if rights ok / freshly created club with data input from user - if club.hasBeenCreated(by: Store.main.userId) { - club.update(fromClub: club) + if newClub.hasBeenCreated(by: Store.main.userId) { + newClub.update(fromClub: club) + do { + try dataStore.clubs.addOrUpdate(instance: newClub) + } catch { + Logger.error(error) + } } - - do { - try dataStore.clubs.addOrUpdate(instance: club) - } catch { - Logger.error(error) - } - + //save into user - if dataStore.user.clubs.contains(where: { $0 == club.id }) == false { - dataStore.user.clubs.append(club.id) + if dataStore.user.clubs.contains(where: { $0 == newClub.id }) == false { + dataStore.user.clubs.append(newClub.id) self.dataStore.saveUser() } dismiss() - selection?(club) + selection?(newClub) } } } diff --git a/PadelClub/Views/Navigation/MainView.swift b/PadelClub/Views/Navigation/MainView.swift index b2e37ce..f7db5b3 100644 --- a/PadelClub/Views/Navigation/MainView.swift +++ b/PadelClub/Views/Navigation/MainView.swift @@ -92,6 +92,27 @@ struct MainView: View { .environmentObject(dataStore) .task { await self._checkSourceFileAvailability() + if Store.main.hasToken() { + do { + try await dataStore.clubs.loadDataFromServerIfAllowed() + } catch { + Logger.error(error) + } + + + let ids = dataStore.user.clubs + var save = false + ids.forEach { clubId in + if dataStore.clubs.findById(clubId) == nil { + dataStore.user.clubs.removeAll(where: { $0 == clubId }) + save = true + } + } + + if save { + dataStore.saveUser() + } + } } // .refreshable { // Task { diff --git a/PadelClub/Views/Navigation/Umpire/UmpireView.swift b/PadelClub/Views/Navigation/Umpire/UmpireView.swift index 5042526..536ce33 100644 --- a/PadelClub/Views/Navigation/Umpire/UmpireView.swift +++ b/PadelClub/Views/Navigation/Umpire/UmpireView.swift @@ -193,12 +193,14 @@ struct UmpireView: View { user.licenceId = player.license if user.clubsObjects().contains(where: { $0.code == player.clubCode }) == false { let userClub = Club.findOrCreate(name: player.clubName!, code: player.clubCode) - do { - try dataStore.clubs.addOrUpdate(instance: userClub) - user.setUserClub(userClub) - } catch { - Logger.error(error) + if userClub.hasBeenCreated(by: Store.main.userId) { + do { + try dataStore.clubs.addOrUpdate(instance: userClub) + } catch { + Logger.error(error) + } } + user.setUserClub(userClub) } self.dataStore.saveUser() } diff --git a/PadelClub/Views/Subscription/Guard.swift b/PadelClub/Views/Subscription/Guard.swift index 0d1fa2e..f383825 100644 --- a/PadelClub/Views/Subscription/Guard.swift +++ b/PadelClub/Views/Subscription/Guard.swift @@ -140,7 +140,7 @@ import LeStorage } var currentPlan: StoreItem? { -// return .monthlyUnlimited + return .monthlyUnlimited // #if DEBUG // return .monthlyUnlimited // #else