multistore
Razmig Sarkissian 2 years ago
parent 53756b3c58
commit f06a54cc67
  1. 8
      PadelClub.xcodeproj/project.pbxproj
  2. 20
      PadelClub/Data/AppSettings.swift
  3. 17
      PadelClub/Data/Tournament.swift
  4. 6
      PadelClub/Manager/FileImportManager.swift
  5. 41
      PadelClub/Manager/SourceFileManager.swift
  6. 2
      PadelClub/Manager/Tips.swift
  7. 26
      PadelClub/Views/Navigation/MainView.swift
  8. 54
      PadelClub/Views/Navigation/PadelClubView.swift
  9. 2
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  10. 86
      PadelClub/Views/Tournament/Screen/Components/InscriptionTipsView.swift
  11. 146
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  12. 9
      PadelClub/Views/Tournament/TournamentView.swift

@ -34,7 +34,6 @@
C4A47DB32B86387500ADC637 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DB22B86387500ADC637 /* AccountView.swift */; };
FF089EB42BB0020000F0AEC7 /* PlayerSexPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EB32BB0020000F0AEC7 /* PlayerSexPickerView.swift */; };
FF089EB62BB00A3800F0AEC7 /* TeamRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EB52BB00A3800F0AEC7 /* TeamRowView.swift */; };
FF089EB82BB00ABF00F0AEC7 /* InscriptionTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EB72BB00ABF00F0AEC7 /* InscriptionTipsView.swift */; };
FF089EBB2BB0120700F0AEC7 /* PlayerPopoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EBA2BB0120700F0AEC7 /* PlayerPopoverView.swift */; };
FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EBC2BB0287D00F0AEC7 /* PlayerView.swift */; };
FF089EBF2BB0B14600F0AEC7 /* FileImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF089EBE2BB0B14600F0AEC7 /* FileImportView.swift */; };
@ -159,6 +158,7 @@
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 */; };
FFDDD40C2B93B2BB00C91A49 /* DeferredViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */; };
FFF8ACCD2B92367B008466FA /* FederalPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF8ACCC2B92367B008466FA /* FederalPlayer.swift */; };
FFF8ACD42B92392C008466FA /* SourceFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF8ACD32B92392C008466FA /* SourceFileManager.swift */; };
@ -244,7 +244,6 @@
C4A47DB22B86387500ADC637 /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = "<group>"; };
FF089EB32BB0020000F0AEC7 /* PlayerSexPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSexPickerView.swift; sourceTree = "<group>"; };
FF089EB52BB00A3800F0AEC7 /* TeamRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamRowView.swift; sourceTree = "<group>"; };
FF089EB72BB00ABF00F0AEC7 /* InscriptionTipsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InscriptionTipsView.swift; sourceTree = "<group>"; };
FF089EBA2BB0120700F0AEC7 /* PlayerPopoverView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerPopoverView.swift; sourceTree = "<group>"; };
FF089EBC2BB0287D00F0AEC7 /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = "<group>"; };
FF089EBE2BB0B14600F0AEC7 /* FileImportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileImportView.swift; sourceTree = "<group>"; };
@ -369,6 +368,7 @@
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>"; };
FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredViewModifier.swift; sourceTree = "<group>"; };
FFF8ACCC2B92367B008466FA /* FederalPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FederalPlayer.swift; sourceTree = "<group>"; };
FFF8ACD32B92392C008466FA /* SourceFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceFileManager.swift; sourceTree = "<group>"; };
@ -499,6 +499,7 @@
C4A47D622B6D3D6500ADC637 /* Club.swift */,
FF8F263E2BAD7D5C00650388 /* Event.swift */,
FF1DC5522BAB354A00FD8220 /* MockData.swift */,
FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */,
FF6EC9012B94799200EA7F5A /* Coredata */,
FF6EC9022B9479B900EA7F5A /* Federal */,
);
@ -789,7 +790,6 @@
FF8F264A2BAE0B4100650388 /* TournamentDatePickerView.swift */,
FF8F26482BAE0B4100650388 /* TournamentFormatSelectionView.swift */,
FF8F26492BAE0B4100650388 /* TournamentLevelPickerView.swift */,
FF089EB72BB00ABF00F0AEC7 /* InscriptionTipsView.swift */,
FF0EC5212BB173E70056B6D1 /* UpdateSourceRankDateView.swift */,
);
path = Components;
@ -1090,6 +1090,7 @@
FF967CF22BAECC0B00A9A3BD /* TeamScore.swift in Sources */,
FFD783FD2B91B9ED000F62A6 /* AgendaDestinationPickerView.swift in Sources */,
FF6EC9002B94794700EA7F5A /* PresentationContext.swift in Sources */,
FFDB1C6D2BB2A02000F1E467 /* AppSettings.swift in Sources */,
FF0EC5202BB16F680056B6D1 /* SwiftParser.swift in Sources */,
C4A47DA92B85F82100ADC637 /* ChangePasswordView.swift in Sources */,
FF6EC8F72B94773200EA7F5A /* RowButtonView.swift in Sources */,
@ -1156,7 +1157,6 @@
C4A47DAD2B85FCCD00ADC637 /* User.swift in Sources */,
FF967D012BAEF0B400A9A3BD /* MatchSummaryView.swift in Sources */,
FF8F26452BAE0A3400650388 /* TournamentDurationManagerView.swift in Sources */,
FF089EB82BB00ABF00F0AEC7 /* InscriptionTipsView.swift in Sources */,
FF1DC5532BAB354A00FD8220 /* MockData.swift in Sources */,
FF967D092BAF3D4000A9A3BD /* TeamDetailView.swift in Sources */,
FF8F26382BAD523300650388 /* PadelRule.swift in Sources */,

@ -0,0 +1,20 @@
//
// AppSettings.swift
// PadelClub
//
// Created by Razmig Sarkissian on 26/03/2024.
//
import Foundation
import LeStorage
class AppSettings: MicroStorable {
static var fileName: String { "appsettings.json" }
required init() {
}
// var id: String = Store.randomId()
}

@ -88,12 +88,20 @@ class Tournament : ModelObject, Storable {
case build
}
func hasEnded() -> Bool {
endDate != nil
}
func state() -> Tournament.State {
if groupStageCount > 0 && groupStages().isEmpty == false {
return .build
}
return .initial
}
func inscriptionClosed() -> Bool {
closedRegistrationDate != nil
}
func groupStages() -> [GroupStage] {
Store.main.filter { $0.tournament == self.id }.sorted(by: \.index)
@ -189,13 +197,10 @@ class Tournament : ModelObject, Storable {
guard let newDate else { return }
rankSourceDate = newDate
let maleDataURLs = SourceFile.allFiles(true).filter { $0.dateFromPath == newDate }
let femaleDataURLs = SourceFile.allFiles(false).filter { $0.dateFromPath == newDate }
let lastRankWoman = femaleDataURLs.compactMap { $0.getUnrankedValue() }.first
let lastRankMan = maleDataURLs.compactMap { $0.getUnrankedValue() }.sorted().last
let lastRankWoman = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: rankSourceDate)
let lastRankMan = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: rankSourceDate)
let dataURLs = maleDataURLs + femaleDataURLs
let dataURLs = SourceFileManager.shared.allFiles.filter({ $0.dateFromPath == newDate })
let sources = dataURLs.map { CSVParser(url: $0) }
await unsortedPlayers().concurrentForEach { player in

@ -15,7 +15,7 @@ class FileImportManager {
return false
}
do {
return try SourceFile.allFilesSortedByDate(false).first(where: {
return try SourceFileManager.shared.allFilesSortedByDate(false).first(where: {
let fileContent = try String(contentsOf: $0)
return fileContent.contains(";\(license);")
}) != nil
@ -30,7 +30,7 @@ class FileImportManager {
return false
}
do {
return try SourceFile.allFilesSortedByDate(true).first(where: {
return try SourceFileManager.shared.allFilesSortedByDate(true).first(where: {
let fileContent = try String(contentsOf: $0)
return fileContent.contains(";\(license);")
}) != nil
@ -253,7 +253,7 @@ class FileImportManager {
}
func importDataFromFFT() async -> String? {
if let importingDate = SourceFile.mostRecentDateAvailable {
if let importingDate = SourceFileManager.shared.mostRecentDateAvailable {
for source in SourceFile.allCases {
for fileURL in source.currentURLs {
let p = readCSV(inputFile: fileURL)

@ -10,8 +10,17 @@ import Foundation
class SourceFileManager {
static let shared = SourceFileManager()
var lastDataSource: String? {
UserDefaults.standard.string(forKey: "lastDataSource")
}
func lastDataSourceDate() -> Date? {
guard let lastDataSource else { return nil }
return URL.importDateFormatter.date(from: lastDataSource)
}
func fetchData() async {
if let mostRecent = SourceFile.mostRecentDateAvailable, let current = Calendar.current.date(byAdding: .month, value: 1, to: mostRecent), current > mostRecent {
if let mostRecent = mostRecentDateAvailable, let current = Calendar.current.date(byAdding: .month, value: 1, to: mostRecent), current > mostRecent {
await fetchData(fromDate: current)
} else {
await fetchData(fromDate: Date())
@ -50,7 +59,7 @@ class SourceFileManager {
} catch {
print("downloadRankingData", error)
if SourceFile.mostRecentDateAvailable == nil {
if mostRecentDateAvailable == nil {
if let previousDate = Calendar.current.date(byAdding: .month, value: -1, to: current) {
await fetchData(fromDate: previousDate)
}
@ -65,7 +74,7 @@ class SourceFileManager {
URL.importDateFormatter.date(from: $0)
}
.filter { date in
SourceFile.allFiles.contains(where: { $0.dateFromPath == date }) == false
allFiles.contains(where: { $0.dateFromPath == date }) == false
}
await dates.concurrentForEach { date in
@ -96,17 +105,18 @@ class SourceFileManager {
}
return months
}
}
enum SourceFile: String, CaseIterable {
case dames = "DAMES"
case messieurs = "MESSIEURS"
static var mostRecentDateAvailable: Date? {
func getUnrankValue(forMale: Bool, rankSourceDate: Date?) -> Int? {
let _rankSourceDate = rankSourceDate ?? mostRecentDateAvailable
let urls = allFiles(forMale).filter { $0.dateFromPath == _rankSourceDate }
return urls.compactMap { $0.getUnrankedValue() }.sorted().last
}
var mostRecentDateAvailable: Date? {
allFiles(false).first?.dateFromPath
}
static func removeAllFilesFromServer() {
func removeAllFilesFromServer() {
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let allFiles = try! FileManager.default.contentsOfDirectory(at: docDir, includingPropertiesForKeys: nil)
allFiles.filter { $0.pathExtension == "csv" }.forEach { url in
@ -114,7 +124,7 @@ enum SourceFile: String, CaseIterable {
}
}
static var allFiles: [URL] {
var allFiles: [URL] {
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let allFiles = try! FileManager.default.contentsOfDirectory(at: docDir, includingPropertiesForKeys: nil).filter({ url in
url.pathExtension == "csv"
@ -123,15 +133,20 @@ enum SourceFile: String, CaseIterable {
return (allFiles + (Bundle.main.urls(forResourcesWithExtension: "csv", subdirectory: nil) ?? [])).sorted(by: \.dateFromPath).reversed()
}
static func allFiles(_ isManPlayer: Bool) -> [URL] {
func allFiles(_ isManPlayer: Bool) -> [URL] {
allFiles.filter({ url in
url.path().contains(isManPlayer ? SourceFile.messieurs.rawValue : SourceFile.dames.rawValue)
})
}
static func allFilesSortedByDate(_ isManPlayer: Bool) -> [URL] {
func allFilesSortedByDate(_ isManPlayer: Bool) -> [URL] {
return allFiles(isManPlayer)
}
}
enum SourceFile: String, CaseIterable {
case dames = "DAMES"
case messieurs = "MESSIEURS"
var filesFromServer: [URL] {
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

@ -157,7 +157,7 @@ struct InscriptionManagerCreateInputTip: Tip {
var message: Text? {
Text("Si le joueur est introuvable, cela indique qu'il n'a jamais fait de compétition, rajoutez-le rapidement manuellement. Padel Club calcul le rang du non-classé ce mois-ci automatiquement.")
Text("Si le joueur est introuvable, cela indique qu'il n'a jamais fait de compétition, rajoutez-le rapidement manuellement. Padel Club calcul le rang du non-classé de ce mois-ci automatiquement.")
}
var image: Image? {

@ -25,16 +25,6 @@ struct MainView: View {
animation: .default)
private var players: FetchedResults<ImportedPlayer>
var _mostRecentDateAvailable: Date? {
SourceFile.mostRecentDateAvailable
}
var _lastDataSourceDate: Date? {
guard let lastDataSource else { return nil }
return URL.importDateFormatter.date(from: lastDataSource)
}
var body: some View {
TabView {
if dataStore.tournaments.isEmpty {
@ -91,18 +81,18 @@ struct MainView: View {
if importingFiles {
HStack(spacing: 20) {
ProgressView()
if let _mostRecentDateAvailable {
if _mostRecentDateAvailable > _lastDataSourceDate ?? .distantPast {
Text("import " + _mostRecentDateAvailable.monthYearFormatted)
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable {
if mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
Text("import " + mostRecentDateAvailable.monthYearFormatted)
}
}
}
} else if let _mostRecentDateAvailable {
if _mostRecentDateAvailable > _lastDataSourceDate ?? .distantPast {
Label(_mostRecentDateAvailable.monthYearFormatted + " disponible", systemImage: "exclamationmark.triangle")
} else if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable {
if mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
Label(mostRecentDateAvailable.monthYearFormatted + " disponible", systemImage: "exclamationmark.triangle")
.labelStyle(.titleAndIcon)
} else {
Label(_mostRecentDateAvailable.monthYearFormatted, systemImage: "checkmark")
Label(mostRecentDateAvailable.monthYearFormatted, systemImage: "checkmark")
.labelStyle(.titleAndIcon)
}
}
@ -118,7 +108,7 @@ struct MainView: View {
checkingFilesAttempt += 1
checkingFiles = false
if let _mostRecentDateAvailable, _mostRecentDateAvailable > _lastDataSourceDate ?? .distantPast {
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
_startImporting()
}
}

@ -23,7 +23,7 @@ struct PadelClubView: View {
var _mostRecentDateAvailable: Date? {
SourceFile.mostRecentDateAvailable
SourceFileManager.shared.mostRecentDateAvailable
}
var _lastDataSourceDate: Date? {
@ -93,7 +93,7 @@ struct PadelClubView: View {
print("check files on internet")
print("check if any files on internet are more recent than here")
checkingFiles = true
await fetchData()
await SourceFileManager.shared.fetchData()
checkingFilesAttempt += 1
checkingFiles = false
}
@ -105,56 +105,6 @@ struct PadelClubView: View {
importingFiles = false
}
}
private func fetchData() async {
if let mostRecent = SourceFile.mostRecentDateAvailable, let current = Calendar.current.date(byAdding: .month, value: 1, to: mostRecent), current > mostRecent {
await fetchData(fromDate: current)
} else {
await fetchData(fromDate: Date())
}
}
private func _removeAllData(fromDate current: Date) {
let lastStringDate = URL.importDateFormatter.string(from: current)
let files = ["MESSIEURS", "MESSIEURS-2", "MESSIEURS-3", "MESSIEURS-4", "DAMES"]
files.forEach { fileName in
NetworkManager.shared.removeRankingData(lastDateString: lastStringDate, fileName: fileName)
}
}
private func fetchData(fromDate current: Date) async {
let lastStringDate = URL.importDateFormatter.string(from: current)
let files = ["MESSIEURS", "MESSIEURS-2", "MESSIEURS-3", "MESSIEURS-4", "DAMES"]
do {
try await withThrowingTaskGroup(of: Void.self) { group in // Mark 1
for file in files {
group.addTask {
try await NetworkManager.shared.downloadRankingData(lastDateString: lastStringDate, fileName: file)
}
}
try await group.waitForAll()
}
if current < Date() {
if let nextCurrent = Calendar.current.date(byAdding: .month, value: 1, to: current) {
await fetchData(fromDate: nextCurrent)
}
}
} catch {
print("downloadRankingData", error)
if _mostRecentDateAvailable == nil {
if let previousDate = Calendar.current.date(byAdding: .month, value: -1, to: current) {
await fetchData(fromDate: previousDate)
}
}
}
}
}
#Preview {

@ -106,7 +106,7 @@ struct SelectablePlayerListView: View {
}
.id(importingFiles)
.overlay {
if let importedFile = SourceFile.mostRecentDateAvailable, importingFiles {
if let importedFile = SourceFileManager.shared.mostRecentDateAvailable, importingFiles {
ContentUnavailableView("Importation en cours", systemImage: "square.and.arrow.down", description: Text("Padel Club récupère les données de \(importedFile.monthYearFormatted)"))
}

@ -1,86 +0,0 @@
//
// InscriptionTipsView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 24/03/2024.
//
import SwiftUI
import TipKit
struct InscriptionTipsView: View {
@Environment(Tournament.self) private var tournament: Tournament
var body: some View {
List {
Section {
let fileTip = InscriptionManagerFileInputTip()
TipView(fileTip) { action in
if action.id == "website" {
} else if action.id == "add-team-file" {
}
}
.tipStyle(tint: nil)
}
Section {
let pasteTip = InscriptionManagerPasteInputTip()
TipView(pasteTip) { action in
if let paste = UIPasteboard.general.string {
//self.pasteField = paste
}
}
.tipStyle(tint: nil)
}
Section {
let searchTip = InscriptionManagerSearchInputTip()
TipView(searchTip) { action in
//presentPlayerCreation = true
}
.tipStyle(tint: nil)
}
Section {
let createTip = InscriptionManagerCreateInputTip()
TipView(createTip) { action in
//presentPlayerSelection = true
}
.tipStyle(tint: nil)
}
Section {
ContentUnavailableView("Aucune équipe", systemImage: "person.2.slash", description: Text("Vous n'avez encore aucune équipe dans votre liste d'attente."))
}
// if let mostRecentDate, let currentRankSourceDate, currentRankSourceDate < mostRecentDate, tournament.isOver == false {
//
// if #available(iOS 17.0, *) {
// Section {
// let tip = InscriptionManagerRankUpdateTip()
// TipView(tip) { action in
// self.currentRankSourceDate = mostRecentDate
// }
// .tipStyle(tint: nil)
// }
// }
//
// rankingDateSourcePickerView(showDateInLabel: false)
// } else if tournament.currentRankSourceDate == nil {
// rankingDateSourcePickerView(showDateInLabel: false)
// }
//
}
}
}
#Preview {
InscriptionTipsView()
.environment(Tournament.mock())
}

@ -32,6 +32,12 @@ struct InscriptionManagerView: View {
let slideToDeleteTip = SlideToDeleteTip()
let inscriptionManagerWomanRankTip = InscriptionManagerWomanRankTip()
let fileTip = InscriptionManagerFileInputTip()
let pasteTip = InscriptionManagerPasteInputTip()
let searchTip = InscriptionManagerSearchInputTip()
let createTip = InscriptionManagerCreateInputTip()
let rankUpdateTip = InscriptionManagerRankUpdateTip()
let categoryOption: PlayerFilterOption
let filterable: Bool
@ -222,7 +228,7 @@ struct InscriptionManagerView: View {
private func _teamRegisteredView() -> some View {
List {
Section {
rankingDateSourcePickerView(showDateInLabel: true)
_rankHandlerView()
let duplicates = tournament.duplicates()
DisclosureGroup {
@ -271,7 +277,7 @@ struct InscriptionManagerView: View {
RowButtonView(title: "Créer une équipe") {
Task {
await MainActor.run() {
// fetchPlayers.nsPredicate = _pastePredicate(pasteField: searchField, mostRecentDate: tournament.rankSourceDate)
fetchPlayers.nsPredicate = _pastePredicate(pasteField: searchField, mostRecentDate: tournament.rankSourceDate)
pasteString = searchField
}
}
@ -327,7 +333,7 @@ struct InscriptionManagerView: View {
if testCreatedPlayers.isEmpty == false || pasteString != nil || editedTeam != nil {
_buildingTeamView()
} else if tournament.unsortedTeams().isEmpty {
InscriptionTipsView()
_inscriptionTipsView()
} else {
_teamRegisteredView()
}
@ -377,15 +383,63 @@ struct InscriptionManagerView: View {
}
}
ToolbarItem(placement: .topBarTrailing) {
Menu {
Button {
presentImportView = true
if editedTeam == nil {
ToolbarItem(placement: .navigationBarTrailing) {
Menu {
if tournament.inscriptionClosed() == false {
Menu {
//sortingTypePickerView
} label: {
Text("Méthode de sélection")
Text(tournament.teamSortingType.localizedLabel())
}
Divider()
rankingDateSourcePickerView(showDateInLabel: true)
if tournament.teamSortingType == .inscriptionDate {
Divider()
//prioritizeClubMembersButton
}
Divider()
Button {
let count = tournament.unsortedTeams().count
if tournament.teamCount > count {
tournament.teamCount = count
}
tournament.closedRegistrationDate = Date()
_save()
} label: {
Label("Clôturer", systemImage: "lock")
}
Divider()
// ShareLink(item: tournament.pasteDataForImporting) {
// Text("Exporter les paires")
// }
Button {
presentImportView = true
} label: {
Label("Importer beach-padel", systemImage: "square.and.arrow.down")
}
if let url = URL(string: "beach-padel.app.fft.fr") {
Link(destination: url) {
Label("beach-padel.app.fft.fr", systemImage: "safari")
}
}
} else {
Button {
tournament.closedRegistrationDate = nil
_save()
} label: {
Label("Ré-ouvrir", systemImage: "lock.open")
}
}
} label: {
Label("Importer", systemImage: "square.and.arrow.down")
if tournament.inscriptionClosed() == false {
LabelOptions()
} else {
Label("Clôturer", systemImage: "lock")
}
}
} label: {
LabelOptions()
}
}
}
@ -415,7 +469,7 @@ struct InscriptionManagerView: View {
guard let first = strings.first else { return }
Task {
await MainActor.run() {
// fetchPlayers.nsPredicate = _pastePredicate(pasteField: first, mostRecentDate: tournament.rankSourceDate)
fetchPlayers.nsPredicate = _pastePredicate(pasteField: first, mostRecentDate: tournament.rankSourceDate)
pasteString = first
}
}
@ -450,13 +504,13 @@ struct InscriptionManagerView: View {
Text("inconnu").tag(nil as Date?)
}
let dates = Array(Set(SourceFile.allFilesSortedByDate(tournament.tournamentCategory.rankingDataSourceMale).map({ $0.dateFromPath }))).sorted().reversed()
let dates = Array(Set(SourceFileManager.shared.allFilesSortedByDate(tournament.tournamentCategory.rankingDataSourceMale).map({ $0.dateFromPath }))).sorted().reversed()
ForEach(dates, id: \.self) { date in
Text(date.monthYearFormatted).tag(date as Date?)
}
} label: {
Text("Classement mensuel utilisé")
Text("Classement utilisé")
if showDateInLabel {
if let currentRankSourceDate {
Text(currentRankSourceDate.monthYearFormatted)
@ -492,6 +546,72 @@ struct InscriptionManagerView: View {
return .all
}
}
@ViewBuilder
func _inscriptionTipsView() -> some View {
List {
Section {
TipView(fileTip) { action in
if action.id == "website" {
} else if action.id == "add-team-file" {
}
}
.tipStyle(tint: nil)
}
Section {
TipView(pasteTip) { action in
if let paste = UIPasteboard.general.string {
self.pasteString = paste
}
}
.tipStyle(tint: nil)
}
Section {
TipView(searchTip) { action in
presentPlayerCreation = true
}
.tipStyle(tint: nil)
}
Section {
TipView(createTip) { action in
presentPlayerSearch = true
}
.tipStyle(tint: nil)
}
Section {
ContentUnavailableView("Aucune équipe", systemImage: "person.2.slash", description: Text("Vous n'avez encore aucune équipe dans votre liste d'attente."))
}
_rankHandlerView()
}
}
@ViewBuilder
func _rankHandlerView() -> some View {
if let mostRecentDate = SourceFileManager.shared.lastDataSourceDate(), let currentRankSourceDate, currentRankSourceDate < mostRecentDate, tournament.hasEnded() == false {
Section {
TipView(rankUpdateTip) { action in
self.currentRankSourceDate = mostRecentDate
}
.tipStyle(tint: nil)
}
rankingDateSourcePickerView(showDateInLabel: false)
} else if tournament.rankSourceDate == nil {
rankingDateSourcePickerView(showDateInLabel: false)
}
}
func _save() {
try? dataStore.tournaments.addOrUpdate(instance: tournament)
}
}
#Preview {

@ -23,12 +23,9 @@ struct TournamentView: View {
if tournament.missingUnrankedValue() {
Button("update NC") {
Task {
tournament.maleUnrankedValue = await FederalPlayer.lastRank(mostRecentDateAvailable: _lastDataSourceDate, man: true)
tournament.femaleUnrankedValue = await FederalPlayer.lastRank(mostRecentDateAvailable: _lastDataSourceDate, man: false)
try? dataStore.tournaments.addOrUpdate(instance: tournament)
}
tournament.femaleUnrankedValue = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: tournament.rankSourceDate)
tournament.maleUnrankedValue = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: tournament.rankSourceDate)
try? dataStore.tournaments.addOrUpdate(instance: tournament)
}
}

Loading…
Cancel
Save