multistore
Razmig Sarkissian 2 years ago
parent e9ec8111b8
commit 3e1c8ae636
  1. 12
      PadelClub.xcodeproj/project.pbxproj
  2. 2
      PadelClub/Data/DataStore.swift
  3. 4
      PadelClub/Data/User.swift
  4. 3
      PadelClub/Utils/LocationManager.swift
  5. 0
      PadelClub/ViewModel/PresentationContext.swift
  6. 0
      PadelClub/ViewModel/Screen.swift
  7. 15
      PadelClub/Views/Club/ClubDetailView.swift
  8. 14
      PadelClub/Views/Club/ClubSearchView.swift
  9. 15
      PadelClub/Views/Navigation/Agenda/ActivityView.swift
  10. 40
      PadelClub/Views/Navigation/Agenda/EmptyActivityView.swift
  11. 24
      PadelClub/Views/Navigation/Agenda/WelcomeView.swift
  12. 2
      PadelClub/Views/Navigation/MainView.swift
  13. 28
      PadelClub/Views/Navigation/PadelClubView.swift
  14. 21
      PadelClub/Views/Navigation/Umpire/UmpireView.swift

@ -248,8 +248,6 @@
FFCFC01A2BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC0192BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift */; }; FFCFC01A2BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC0192BBC5A8500B82851 /* MatchTypeSmallSelectionView.swift */; };
FFCFC01C2BBC5AAA00B82851 /* SetDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */; }; FFCFC01C2BBC5AAA00B82851 /* SetDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */; };
FFD783FF2B91BA42000F62A6 /* PadelClubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD783FE2B91BA42000F62A6 /* PadelClubView.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 */; }; FFDB1C6D2BB2A02000F1E467 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */; };
FFDB1C732BB2CFE900F1E467 /* MySortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */; }; FFDB1C732BB2CFE900F1E467 /* MySortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */; };
FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.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 = "<group>"; }; FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDescriptor.swift; sourceTree = "<group>"; };
FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadelClubView.swift; sourceTree = "<group>"; }; FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadelClubView.swift; sourceTree = "<group>"; };
FFD784002B91BF79000F62A6 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; }; FFD784002B91BF79000F62A6 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
FFD784012B91C1B4000F62A6 /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
FFD784032B91C280000F62A6 /* EmptyActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyActivityView.swift; sourceTree = "<group>"; };
FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; }; FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = "<group>"; };
FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySortDescriptor.swift; sourceTree = "<group>"; }; FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySortDescriptor.swift; sourceTree = "<group>"; };
FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredViewModifier.swift; sourceTree = "<group>"; }; FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredViewModifier.swift; sourceTree = "<group>"; };
@ -936,8 +932,6 @@
FF3F74F92B91A018004CFE0E /* Screen */ = { FF3F74F92B91A018004CFE0E /* Screen */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FF6EC8FD2B94792300EA7F5A /* Screen.swift */,
FF6EC8FF2B94794700EA7F5A /* PresentationContext.swift */,
FF70916D2B9108C600AB08DA /* InscriptionManagerView.swift */, FF70916D2B9108C600AB08DA /* InscriptionManagerView.swift */,
FF8F26422BADFE5B00650388 /* TournamentSettingsView.swift */, FF8F26422BADFE5B00650388 /* TournamentSettingsView.swift */,
FF8F26532BAE1E4400650388 /* TableStructureView.swift */, FF8F26532BAE1E4400650388 /* TableStructureView.swift */,
@ -984,6 +978,8 @@
FF3F74FD2B91A087004CFE0E /* ViewModel */ = { FF3F74FD2B91A087004CFE0E /* ViewModel */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FF6EC8FD2B94792300EA7F5A /* Screen.swift */,
FF6EC8FF2B94794700EA7F5A /* PresentationContext.swift */,
FF7091652B90F0B000AB08DA /* TabDestination.swift */, FF7091652B90F0B000AB08DA /* TabDestination.swift */,
FF025AEC2BD1513700A86CF8 /* AppScreen.swift */, FF025AEC2BD1513700A86CF8 /* AppScreen.swift */,
FF3F74FE2B91A2D4004CFE0E /* AgendaDestination.swift */, FF3F74FE2B91A2D4004CFE0E /* AgendaDestination.swift */,
@ -1176,8 +1172,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FF82CFC82B9132AF00B0CAF2 /* ActivityView.swift */, FF82CFC82B9132AF00B0CAF2 /* ActivityView.swift */,
FFD784032B91C280000F62A6 /* EmptyActivityView.swift */,
FFD784012B91C1B4000F62A6 /* WelcomeView.swift */,
FF59FFB22B90EFAC0061EFF9 /* EventListView.swift */, FF59FFB22B90EFAC0061EFF9 /* EventListView.swift */,
FF5D0D8A2BB4D1E3005CB568 /* CalendarView.swift */, FF5D0D8A2BB4D1E3005CB568 /* CalendarView.swift */,
); );
@ -1596,7 +1590,6 @@
FF9AC3952BE3627B00C2E883 /* GroupStageTeamReplacementView.swift in Sources */, FF9AC3952BE3627B00C2E883 /* GroupStageTeamReplacementView.swift in Sources */,
FF4C7F022BBBD7150031B6A3 /* TabItemModifier.swift in Sources */, FF4C7F022BBBD7150031B6A3 /* TabItemModifier.swift in Sources */,
FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */, FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */,
FFD784042B91C280000F62A6 /* EmptyActivityView.swift in Sources */,
FF0E0B6D2BC254C6005F00A9 /* TournamentScheduleView.swift in Sources */, FF0E0B6D2BC254C6005F00A9 /* TournamentScheduleView.swift in Sources */,
FF025AF12BD1AEBD00A86CF8 /* MatchFormatStorageView.swift in Sources */, FF025AF12BD1AEBD00A86CF8 /* MatchFormatStorageView.swift in Sources */,
FF3F74F62B919E45004CFE0E /* UmpireView.swift in Sources */, FF3F74F62B919E45004CFE0E /* UmpireView.swift in Sources */,
@ -1618,7 +1611,6 @@
FFF964532BC262B000EEF017 /* PlanningSettingsView.swift in Sources */, FFF964532BC262B000EEF017 /* PlanningSettingsView.swift in Sources */,
FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */, FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */,
FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */, FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */,
FFD784022B91C1B4000F62A6 /* WelcomeView.swift in Sources */,
FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */, FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */,
FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */, FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */,
FF967D032BAEF0C000A9A3BD /* MatchDetailView.swift in Sources */, FF967D032BAEF0C000A9A3BD /* MatchDetailView.swift in Sources */,

@ -105,7 +105,7 @@ class DataStore: ObservableObject {
if let _ = Guard.main.currentPlan { if let _ = Guard.main.currentPlan {
return .creation return .creation
} }
if let user = self.user, user.club != nil { if let user = self.user, user.clubs != nil {
if user.umpireCode != nil { if user.umpireCode != nil {
return .creation return .creation
} else { } else {

@ -24,7 +24,7 @@ class User: UserBase, Storable {
public var id: String = Store.randomId() public var id: String = Store.randomId()
public var username: String public var username: String
public var email: String public var email: String
var club: String? var clubs: [String]?
var umpireCode: String? var umpireCode: String?
var licenceId: String? var licenceId: String?
var firstName: String var firstName: String
@ -61,7 +61,7 @@ class User: UserBase, Storable {
case _id = "id" case _id = "id"
case _username = "username" case _username = "username"
case _email = "email" case _email = "email"
case _club = "club" case _clubs = "clubs"
case _umpireCode = "umpireCode" case _umpireCode = "umpireCode"
case _licenceId = "licenceId" case _licenceId = "licenceId"
case _firstName = "firstName" case _firstName = "firstName"

@ -17,7 +17,6 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var requestStarted: Bool = false @Published var requestStarted: Bool = false
@Published var userReadableCityOrZipcode: String = "" @Published var userReadableCityOrZipcode: String = ""
@Published var lastError: Error? = nil @Published var lastError: Error? = nil
var shouldRequestLocation: Bool = false
override init() { override init() {
super.init() super.init()
@ -41,13 +40,11 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse || manager.authorizationStatus == .authorizedAlways { if manager.authorizationStatus == .authorizedWhenInUse || manager.authorizationStatus == .authorizedAlways {
if requestStarted == false && shouldRequestLocation {
DispatchQueue.main.async { DispatchQueue.main.async {
self.requestLocation() self.requestLocation()
} }
} }
} }
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("locationManager didFailWithError", error) print("locationManager didFailWithError", error)

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import LeStorage
struct ClubDetailView: View { struct ClubDetailView: View {
@Bindable var club: Club @Bindable var club: Club
@ -138,6 +139,20 @@ struct ClubDetailView: View {
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar(.visible, for: .navigationBar) .toolbar(.visible, for: .navigationBar)
.toolbarBackground(.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 { .onDisappear {
if displayContext == .edition { if displayContext == .edition {
try? dataStore.clubs.addOrUpdate(instance: club) try? dataStore.clubs.addOrUpdate(instance: club)

@ -25,6 +25,8 @@ struct ClubSearchView: View {
@State private var getForwardCityList: [CLPlacemark] = [] @State private var getForwardCityList: [CLPlacemark] = []
@State private var searchPresented: Bool = false @State private var searchPresented: Bool = false
@State private var showingSettingsAlert = false @State private var showingSettingsAlert = false
@State private var presentClubCreationView: Bool = false
var displayContext: DisplayContext = .edition var displayContext: DisplayContext = .edition
var club: Club? var club: Club?
@ -141,7 +143,7 @@ struct ClubSearchView: View {
if searchAttempted { if searchAttempted {
Label("Aucun club trouvé", systemImage: "mappin.slash") Label("Aucun club trouvé", systemImage: "mappin.slash")
} else { } else {
Text("Recherche de club") Label("Recherche de club", systemImage: "location.circle")
} }
} description: { } 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.") 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") { RowButtonView("Chercher une ville ou un code postal") {
searchPresented = true searchPresented = true
} }
if searchAttempted {
RowButtonView("Créer un club manuellement") {
presentClubCreationView = true
}
}
} }
} }
} else { } else {
ContentUnavailableView("recherche en cours", systemImage: "mappin.and.ellipse", description: Text("recherche des clubs autour de vous")) 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(isPresented: $showingSettingsAlert) {
Alert( Alert(
title: Text("Réglages"), title: Text("Réglages"),

@ -20,6 +20,7 @@ struct ActivityView: View {
@State private var isGatheringFederalTournaments: Bool = false @State private var isGatheringFederalTournaments: Bool = false
@State private var error: Error? @State private var error: Error?
@State private var uuid: UUID = UUID() @State private var uuid: UUID = UUID()
@State private var presentClubSearchView: Bool = false
var runningTournaments: [FederalTournamentHolder] { var runningTournaments: [FederalTournamentHolder] {
dataStore.tournaments.filter({ $0.endDate == nil }) dataStore.tournaments.filter({ $0.endDate == nil })
@ -199,6 +200,10 @@ struct ActivityView: View {
.environment(navigation) .environment(navigation)
.tint(.master) .tint(.master)
} }
.sheet(isPresented: $presentClubSearchView) {
ClubImportView()
.tint(.master)
}
} }
} }
} }
@ -245,11 +250,17 @@ struct ActivityView: View {
RowButtonView("Créer un nouvel événement") { RowButtonView("Créer un nouvel événement") {
newTournament = Tournament.newEmptyInstance() newTournament = Tournament.newEmptyInstance()
} }
if dataStore.clubs.isEmpty {
RowButtonView("Chercher l'un de vos clubs") {
presentClubSearchView = true
}
} else {
RowButtonView("Importer via Tenup") { RowButtonView("Importer via Tenup") {
navigation.agendaDestination = .tenup navigation.agendaDestination = .tenup
} }
} }
} }
}
private func _endedEmptyView() -> some View { private func _endedEmptyView() -> some View {
ContentUnavailableView { ContentUnavailableView {
@ -264,9 +275,9 @@ struct ActivityView: View {
ContentUnavailableView { ContentUnavailableView {
Label("Aucun tournoi", systemImage: "shield.slash") Label("Aucun tournoi", systemImage: "shield.slash")
} description: { } 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: { } actions: {
RowButtonView("Choisir mes clubs préférés") { RowButtonView("Choisir mes clubs") {
navigation.selectedTab = .umpire navigation.selectedTab = .umpire
} }
} }

@ -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()
}

@ -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()
}

@ -101,7 +101,7 @@ struct MainView: View {
checkingFiles = false checkingFiles = false
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast { if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
_startImporting() //_startImporting()
} }
} }

@ -11,7 +11,7 @@ import SwiftData
struct PadelClubView: View { struct PadelClubView: View {
@State private var checkingFilesAttempt: Int = 0 @State private var checkingFilesAttempt: Int = 0
@State private var checkingFiles: Bool = false @State private var checkingFiles: Bool = false
@State private var importingFiles: Bool = false @AppStorage("importingFiles") var importingFiles: Bool = false
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@ -72,18 +72,20 @@ struct PadelClubView: View {
Text(monthData.monthKey) Text(monthData.monthKey)
} }
} }
//
// if players.isEmpty { if importingFiles {
// ContentUnavailableView { ContentUnavailableView("Importation en cours", systemImage: "server.rack", description: Text("Une importation des données fédérales publiques est en cours, veuillez patienter."))
// Label("Aucun joueur importé", systemImage: "person.slash") } else if (players.isEmpty || lastDataSource == nil) {
// } description: { ContentUnavailableView {
// Text("Padel peut importer toutes les données publique de la FFT concernant tous les compétiteurs et compétitrices.") Label("Aucun joueur importé", systemImage: "person.slash")
// } actions: { } description: {
// RowButtonView("Démarrer l'importation") { Text("Padel Club peut importer toutes les données publiques de la FFT concernant tous les compétiteurs et compétitrices.")
// _startImporting() } actions: {
// } RowButtonView("Démarrer l'importation") {
// } _startImporting()
// } }
}
}
} }
.task { .task {
await self._checkSourceFileAvailability() await self._checkSourceFileAvailability()

@ -59,7 +59,11 @@ struct UmpireView: View {
user.licenceId = player.license user.licenceId = player.license
let club = dataStore.clubs.first(where: { $0.code == player.clubCode }) ?? Club(name: player.clubName!, code: player.clubCode!) let club = dataStore.clubs.first(where: { $0.code == player.clubCode }) ?? Club(name: player.clubName!, code: player.clubCode!)
try? dataStore.clubs.addOrUpdate(instance: club) 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) dataStore.setUser(user)
} }
}) })
@ -82,22 +86,19 @@ struct UmpireView: View {
} }
} }
if let clubId = user.club { if let clubs = user.clubs {
if let club = dataStore.clubs.findById(clubId) {
Section { Section {
ForEach(clubs) { clubId in
if let club = dataStore.clubs.findById(clubId) {
NavigationLink { NavigationLink {
ClubDetailView(club: club, displayContext: .edition) ClubDetailView(club: club, displayContext: .edition)
} label: { } label: {
ClubRowView(club: club) ClubRowView(club: club)
} }
} header: {
Text("Mon club")
} footer: {
Button("supprimer", role: .destructive) {
user.club = nil
dataStore.setUser(user)
} }
} }
} header: {
Text("Mes clubs")
} }
} }
} }
@ -109,7 +110,7 @@ struct UmpireView: View {
LabeledContent { LabeledContent {
Text(dataStore.clubs.count.formatted()) Text(dataStore.clubs.count.formatted())
} label: { } label: {
Label("Mes clubs favoris", systemImage: "house.and.flag.circle.fill") Label("Mes clubs", systemImage: "house.and.flag.circle.fill")
} }
} }
} }

Loading…
Cancel
Save