Laurent 2 years ago
commit 4253ba2c31
  1. 12
      PadelClub/Data/Match.swift
  2. 13
      PadelClub/Data/MatchScheduler.swift
  3. 7
      PadelClub/Data/Tournament.swift
  4. 7
      PadelClub/Utils/Tips.swift
  5. 32
      PadelClub/Views/Calling/CallMessageCustomizationView.swift
  6. 19
      PadelClub/Views/Club/CourtView.swift
  7. 17
      PadelClub/Views/Components/FortuneWheelView.swift
  8. 2
      PadelClub/Views/Components/MatchListView.swift
  9. 2
      PadelClub/Views/GroupStage/Shared/GroupStageTeamReplacementView.swift
  10. 2
      PadelClub/Views/Match/MatchSummaryView.swift
  11. 33
      PadelClub/Views/Planning/CourtAvailabilitySettingsView.swift
  12. 4
      PadelClub/Views/Planning/PlanningSettingsView.swift
  13. 4
      PadelClub/Views/Player/Components/PlayerSexPickerView.swift
  14. 44
      PadelClub/Views/Round/RoundView.swift
  15. 2
      PadelClub/Views/Score/EditScoreView.swift
  16. 2
      PadelClub/Views/Team/TeamRowView.swift
  17. 9
      PadelClub/Views/Tournament/FileImportView.swift
  18. 8
      PadelClub/Views/Tournament/Screen/BroadcastView.swift
  19. 6
      PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift
  20. 2
      PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift
  21. 8
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  22. 10
      PadelClub/Views/Tournament/TournamentInitView.swift
  23. 11
      PadelClub/Views/Tournament/TournamentView.swift

@ -27,12 +27,12 @@ class Match: ModelObject, Storable {
var winningTeamId: String?
var losingTeamId: String?
//var broadcasted: Bool
//var name: String?
private var name: String?
//var order: Int
var disabled: Bool = false
private(set) var courtIndex: Int?
internal init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, disabled: Bool = false, courtIndex: Int? = nil) {
internal init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, name: String? = nil, disabled: Bool = false, courtIndex: Int? = nil) {
self.round = round
self.groupStage = groupStage
self.startDate = startDate
@ -44,11 +44,9 @@ class Match: ModelObject, Storable {
self.winningTeamId = winningTeamId
self.losingTeamId = losingTeamId
self.disabled = disabled
self.name = name
self.courtIndex = courtIndex
// self.broadcasted = broadcasted
// self.name = name
// self.order = order
}
@ -271,7 +269,7 @@ class Match: ModelObject, Storable {
}
func roundTitle() -> String? {
if groupStage != nil { return "Poule" }
if groupStage != nil { return groupStageObject?.groupStageTitle() }
else if let roundObject { return roundObject.roundTitle() }
else { return nil }
}
@ -630,7 +628,7 @@ class Match: ModelObject, Storable {
case _winningTeamId = "winningTeamId"
case _losingTeamId = "losingTeamId"
// case _broadcasted = "broadcasted"
// case _name = "name"
case _name = "name"
// case _order = "order"
case _disabled = "disabled"
}

@ -111,7 +111,7 @@ class MatchScheduler : ModelObject, Storable {
return lastDate
}
func groupStageDispatcher(numberOfCourtsAvailablePerRotation: Int, groupStages: [GroupStage], startingDate: Date?) -> GroupStageMatchDispatcher {
func groupStageDispatcher(numberOfCourtsAvailablePerRotation: Int, groupStages: [GroupStage], startingDate: Date) -> GroupStageMatchDispatcher {
let _groupStages = groupStages
@ -156,7 +156,16 @@ class MatchScheduler : ModelObject, Storable {
(0..<numberOfCourtsAvailablePerRotation).forEach { courtIndex in
//print(mt.map { ($0.bracket!.index.intValue, counts[$0.bracket!.index.intValue]) })
if let first = rotationMatches.first(where: { match in
teamsPerRotation[rotationIndex]!.allSatisfy({ match.containsTeamId($0) == false }) == true
let estimatedDuration = match.matchFormat.getEstimatedDuration(additionalEstimationDuration)
let timeIntervalToAdd = (Double(rotationIndex)) * Double(estimatedDuration) * 60
let rotationStartDate: Date = startingDate.addingTimeInterval(timeIntervalToAdd)
let courtsUnavailable = courtsUnavailable(startDate: rotationStartDate, duration: match.matchFormat.getEstimatedDuration(additionalEstimationDuration))
if courtIndex >= numberOfCourtsAvailablePerRotation - courtsUnavailable {
return false
} else {
return teamsPerRotation[rotationIndex]!.allSatisfy({ match.containsTeamId($0) == false }) == true
}
}) {
let timeMatch = GroupStageTimeMatch(matchID: first.id, rotationIndex: rotationIndex, courtIndex: courtIndex, groupIndex: first.groupStageObject!.index)
slots.append(timeMatch)

@ -96,7 +96,7 @@ class Tournament : ModelObject, Storable {
case _publishBrackets = "publishBrackets"
}
internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = true, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishManually: Bool = false, publishTeams: Bool = false, publishWaitingList: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false) {
internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = false, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil, additionalEstimationDuration: Int = 0, isDeleted: Bool = false, publishManually: Bool = false, publishTeams: Bool = false, publishWaitingList: Bool = false, publishSummons: Bool = false, publishGroupStages: Bool = false, publishBrackets: Bool = false) {
self.event = event
self.name = name
self.startDate = startDate
@ -363,8 +363,9 @@ class Tournament : ModelObject, Storable {
}
func seeds() -> [TeamRegistration] {
let seeds = max(teamCount - groupStageCount * teamsPerGroupStage, 0)
return Array(selectedSortedTeams().prefix(seeds))
let selectedSortedTeams = selectedSortedTeams()
let seeds = max(selectedSortedTeams.count - groupStageCount * teamsPerGroupStage, 0)
return Array(selectedSortedTeams.prefix(seeds))
}
func availableSeeds() -> [TeamRegistration] {

@ -339,9 +339,12 @@ struct TournamentPublishingTip: Tip {
Text("Gestion de la publication")
}
enum ActionKey: String {
case showPadelClub = "show-padel-club"
}
var message: Text? {
let messageString = "Padel Club vous permet de publier votre tournoi et rendre accessible à tous les résultats des matchs et l'évolution de l'événement. Les informations seront accessible sur le site [Padel Club](\(URLs.padelClub))."
return Text(.init(messageString))
Text("Padel Club vous permet de publier votre tournoi et rendre accessible à tous les résultats des matchs et l'évolution de l'événement. Les informations seront accessible sur le site Padel Club.")
}
var image: Image? {

@ -46,17 +46,18 @@ struct CallMessageCustomizationView: View {
var finalMessage: String? {
let localizedCalled = "convoqué" + (tournament.tournamentCategory == .women ? "e" : "") + "s"
return "Bonjour,\n\nVous êtes \(localizedCalled) pour jouer en \(RoundRule.roundName(fromRoundIndex: 2).lowercased()) du \(tournament.tournamentTitle()) au \(clubName) le \(Date().formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(Date().formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(customCallMessageSignature)"
return "Bonjour,\n\nVous êtes \(localizedCalled) pour jouer en \(RoundRule.roundName(fromRoundIndex: 2).lowercased()) du \(tournament.tournamentTitle()) au \(clubName) le \(tournament.startDate).formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(tournament.startDate.formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(customCallMessageSignature)"
}
var body: some View {
@Bindable var user = dataStore.user
List {
_renderingView()
.disabled(true)
_optionsView()
_editorView()
if user.summonsUseFullCustomMessage {
if user.summonsUseFullCustomMessage && tournament.isFree() == false {
_paymentMethodsView()
}
@ -138,9 +139,19 @@ struct CallMessageCustomizationView: View {
Text("Information supplémentaire")
}
} footer: {
if user.summonsUseFullCustomMessage == false {
HStack {
Spacer()
FooterButtonView("éditer") {
focusedField = .body
}
}
}
}
if user.summonsUseFullCustomMessage {
LazyVStack(alignment: .leading) {
Text("Utilisez ces balises")
Section {
LazyHStack {
FooterButtonView("#titre") {
customCallMessageBody.append("#titre")
focusedField = .body
@ -170,13 +181,8 @@ struct CallMessageCustomizationView: View {
focusedField = .body
}
}
} else {
HStack {
Spacer()
FooterButtonView("éditer") {
focusedField = .body
}
}
} header: {
Text("Utilisez ces balises")
}
}
}
@ -219,12 +225,14 @@ struct CallMessageCustomizationView: View {
private func _renderingView() -> some View {
@Bindable var user = dataStore.user
Section {
Group {
if user.summonsUseFullCustomMessage {
Text(self.computedFullCustomMessage())
}
else if let finalMessage {
Text(finalMessage)
}
}.italic().foregroundStyle(.gray)
} header: {
Text("Rendu généré automatiquement")
}
@ -248,7 +256,7 @@ struct CallMessageCustomizationView: View {
Text("Options")
}
if user.summonsDisplayEntryFee && user.summonsUseFullCustomMessage == false {
if user.summonsDisplayEntryFee && user.summonsUseFullCustomMessage == false && tournament.isFree() == false {
_paymentMethodsView()
}
}

@ -25,9 +25,24 @@ struct CourtView: View {
.keyboardType(.alphabet)
.multilineTextAlignment(.trailing)
.frame(maxWidth: .infinity)
.onSubmit {
court.name = name
if name.isEmpty {
court.name = nil
}
try? dataStore.courts.addOrUpdate(instance: court)
}
} label: {
Text("Nom du terrain")
}
} footer: {
if court.name?.isEmpty == false {
FooterButtonView("nom par défaut") {
name = ""
court.name = nil
try? dataStore.courts.addOrUpdate(instance: court)
}
}
}
Section {
@ -39,10 +54,6 @@ struct CourtView: View {
}
}
}
.onChange(of: name) {
court.name = name
try? dataStore.courts.addOrUpdate(instance: court)
}
.onChange(of: [court.indoor, court.exitAllowed]) {
try? dataStore.courts.addOrUpdate(instance: court)
}

@ -128,13 +128,14 @@ struct SpinDrawView: View {
}
}
Section {
Text("XXX")
Text("XXX")
Text("XXX")
} header: {
Text("Comité du tournoi")
}
//todo
// Section {
// Text("XXX")
// Text("XXX")
// Text("XXX")
// } header: {
// Text("Comité du tournoi")
// }
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
@ -286,7 +287,7 @@ struct FortuneWheelView: View {
Text(string).bold()
}
}
.padding(.trailing, 30)
.padding(.trailing, 40)
.rotationEffect(.degrees(Double(index) * (360 / Double(segments.count)) + (360 / Double(segments.count) / 2)))
.foregroundColor(.white)
.position(arcPosition(index: index, radius: radius))

@ -11,7 +11,7 @@ struct MatchListView: View {
@EnvironmentObject var dataStore: DataStore
let section: String
let matches: [Match]
var matchViewStyle: MatchViewStyle = .sectionedStandardStyle
var matchViewStyle: MatchViewStyle = .standardStyle
@State var isExpanded: Bool = true

@ -72,6 +72,8 @@ struct GroupStageTeamReplacementView: View {
}
.labelsHidden()
.pickerStyle(.inline)
} header: {
Text("Remplacer")
} footer: {
Text("Remplacement de l'équipe ou d'un joueur particulier")
}

@ -76,10 +76,12 @@ struct MatchSummaryView: View {
Text(tournament.tournamentTitle())
}
HStack {
if matchViewStyle != .sectionedStandardStyle {
if let roundTitle {
Text(roundTitle)
}
Text(matchTitle)
}
Spacer()
if let courtName {
Spacer()

@ -33,6 +33,22 @@ struct CourtAvailabilitySettingsView: View {
if let dates = courtsUnavailability[key] {
Section {
ForEach(dates) { dateInterval in
Menu {
Button("dupliquer") {
let duplicatedDateInterval = DateInterval(event: event.id, courtIndex: (courtIndex+1)%tournament.courtCount, startDate: dateInterval.startDate, endDate: dateInterval.endDate)
try? dataStore.dateIntervals.addOrUpdate(instance: duplicatedDateInterval)
}
Button("éditer") {
editingSlot = dateInterval
courtIndex = dateInterval.courtIndex
startDate = dateInterval.startDate
endDate = dateInterval.endDate
showingPopover = true
}
Button("effacer", role: .destructive) {
try? dataStore.dateIntervals.delete(instance: dateInterval)
}
} label: {
HStack {
VStack(alignment: .leading, spacing: 0) {
Text(dateInterval.startDate.localizedTime()).font(.largeTitle)
@ -50,22 +66,7 @@ struct CourtAvailabilitySettingsView: View {
Text(dateInterval.endDate.localizedDay()).font(.caption)
}
}
.contextMenu(menuItems: {
Button("dupliquer") {
let duplicatedDateInterval = DateInterval(event: event.id, courtIndex: (courtIndex+1)%tournament.courtCount, startDate: dateInterval.startDate, endDate: dateInterval.endDate)
try? dataStore.dateIntervals.addOrUpdate(instance: duplicatedDateInterval)
}
Button("éditer") {
editingSlot = dateInterval
courtIndex = dateInterval.courtIndex
startDate = dateInterval.startDate
endDate = dateInterval.endDate
showingPopover = true
}
Button("effacer", role: .destructive) {
try? dataStore.dateIntervals.delete(instance: dateInterval)
}
})
.swipeActions {
Button(role: .destructive) {
try? dataStore.dateIntervals.delete(instance: dateInterval)
@ -95,6 +96,8 @@ struct CourtAvailabilitySettingsView: View {
Text("Vous pouvez précisez l'indisponibilité d'une ou plusieurs terrains, que ce soit pour une journée entière ou un créneau précis.")
} actions: {
RowButtonView("Ajouter une indisponibilité", systemImage: "plus.circle.fill") {
startDate = tournament.startDate
endDate = tournament.startDate.addingTimeInterval(5400)
showingPopover = true
}
}

@ -42,15 +42,13 @@ struct PlanningSettingsView: View {
}
} header: {
Text("Démarrage et durée du tournoi")
} footer: {
Text("todo: Expliquer ce que ca fait")
}
Section {
TournamentFieldsManagerView(localizedStringKey: "Terrains maximum", count: $tournament.courtCount)
if tournament.groupStages().isEmpty == false {
TournamentFieldsManagerView(localizedStringKey: "Terrains par poule", count: $groupStageCourtCount, max: tournament.maximumCourtsPerGroupSage())
TournamentFieldsManagerView(localizedStringKey: "Nombre de poule en même temps", count: $groupStageCourtCount, max: tournament.groupStageCount)
}
if let event = tournament.eventObject() {

@ -17,8 +17,8 @@ struct PlayerSexPickerView: View {
Text(player.playerLabel())
Spacer()
Picker(selection: $player.sex) {
Text("Homme").tag(PlayerRegistration.PlayerSexType.male)
Text("Femme").tag(PlayerRegistration.PlayerSexType.female)
Text("Homme").tag(PlayerRegistration.PlayerSexType.male as PlayerRegistration.PlayerSexType?)
Text("Femme").tag(PlayerRegistration.PlayerSexType.female as PlayerRegistration.PlayerSexType?)
} label: {
}

@ -11,6 +11,15 @@ struct RoundView: View {
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var dataStore: DataStore
@State private var selectedSeedGroup: SeedInterval?
var showVisualDrawView: Binding<Bool> { Binding(
get: { selectedSeedGroup != nil },
set: {
if $0 == false {
selectedSeedGroup = nil
}
}
)}
var round: Round
@ -50,6 +59,7 @@ struct RoundView: View {
}
} else if let availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: round.index) {
Section {
RowButtonView("Placer \(availableSeedGroup.localizedLabel())" + ((availableSeedGroup.isFixed() == false) ? " au hasard" : "")) {
tournament.setSeeds(inRoundIndex: round.index, inSeedGroup: availableSeedGroup)
if tournament.availableSeeds().isEmpty {
@ -57,22 +67,13 @@ struct RoundView: View {
self.isEditingTournamentSeed.wrappedValue = false
}
}
}
if (availableSeedGroup.isFixed() == false) {
let seeds = tournament.seeds(inSeedGroup: availableSeedGroup)
let availableSeedSpot = tournament.availableSeedSpot(inRoundIndex: round.index)
NavigationLink {
SpinDrawView(drawees: seeds, segments: availableSeedSpot) { draws in
draws.forEach { drawResult in
print(seeds[drawResult.drawee].teamLabel())
print(availableSeedSpot[drawResult.drawIndex].matchTitle())
seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: false)
Section {
RowButtonView("Tirage au sort \(availableSeedGroup.localizedLabel()) visuel") {
self.selectedSeedGroup = availableSeedGroup
}
try? dataStore.matches.addOrUpdate(contentOfs: availableSeedSpot)
try? dataStore.teamRegistrations.addOrUpdate(contentOfs: seeds)
}
} label: {
Text("ou proposer le tirage au sort \(availableSeedGroup.localizedLabel())")
}
}
}
@ -97,6 +98,23 @@ struct RoundView: View {
}
}
}
.sheet(isPresented: showVisualDrawView) {
if let availableSeedGroup = selectedSeedGroup {
let seeds = tournament.seeds(inSeedGroup: availableSeedGroup)
let availableSeedSpot = tournament.availableSeedSpot(inRoundIndex: round.index)
NavigationStack {
SpinDrawView(drawees: seeds, segments: availableSeedSpot) { draws in
draws.forEach { drawResult in
print(seeds[drawResult.drawee].teamLabel())
print(availableSeedSpot[drawResult.drawIndex].matchTitle())
seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: false)
}
try? dataStore.matches.addOrUpdate(contentOfs: availableSeedSpot)
try? dataStore.teamRegistrations.addOrUpdate(contentOfs: seeds)
}
}
}
}
.headerProminence(.increased)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {

@ -95,7 +95,7 @@ struct EditScoreView: View {
dismiss()
}
} footer: {
Text("Met à jour le score pour la diffusion, ne termine pas la rencontre")
Text("Met à jour le score, ne termine pas la rencontre")
}
}
}

@ -16,7 +16,7 @@ struct TeamRowView: View {
LabeledContent {
TeamWeightView(team: team, teamPosition: teamPosition)
} label: {
Text(team.teamLabel(.short))
Text(team.teamLabel(.wide))
if let callDate = team.callDate, displayCallDate {
Text("Déjà convoquée \(callDate.localizedDate())")
.foregroundStyle(.red)

@ -56,7 +56,7 @@ struct FileImportView: View {
await _startImport(fileContent: fileContent)
}
}
.disabled(fileContent == nil)
.disabled(fileContent == nil || convertingFile)
} footer: {
if fileProvider == .frenchFederation {
let footerString = "Fichier provenant de [beach-padel.app.fft.fr](\(URLs.beachPadel.rawValue))"
@ -95,7 +95,7 @@ struct FileImportView: View {
LabeledContent {
ProgressView()
} label: {
Text("Importation en cours")
Text("Conversion du fichier en cours")
}
}
}
@ -171,13 +171,14 @@ struct FileImportView: View {
case .success(let fileurls):
if let selectedFile = fileurls.first {
if selectedFile.startAccessingSecurityScopedResource() {
convertingFile = true
errorMessage = nil
teams.removeAll()
Task {
do {
if selectedFile.lastPathComponent.hasSuffix("xls") {
convertingFile = true
fileContent = try await CloudConvert.manager.uploadFile(selectedFile)
convertingFile = false
} else {
fileContent = try String(contentsOf: selectedFile)
}
@ -242,7 +243,6 @@ struct FileImportView: View {
func _startImport(fileContent: String) async {
await MainActor.run {
convertingFile = true
errorMessage = nil
teams.removeAll()
}
@ -252,7 +252,6 @@ struct FileImportView: View {
self.teams = await FileImportManager.shared.createTeams(from: fileContent, tournament: tournament, fileProvider: fileProvider)
await MainActor.run {
convertingFile = false
didImport = true
}
}

@ -28,10 +28,16 @@ struct BroadcastView: View {
var body: some View {
@Bindable var tournament = tournament
List {
TipView(tournamentPublishingTip)
Section {
TipView(tournamentPublishingTip) { action in
UIApplication.shared.open(URLs.padelClub.url)
}
.tipStyle(tint: nil)
}
Section {
TipView(tournamentTVBroadcastTip)
.tipStyle(tint: nil)
}
if tournament.publishManually == false {
Section {

@ -83,11 +83,11 @@ struct TournamentClubSettingsView: View {
private func _courtView(atIndex index: Int, tournamentClub: Club) -> some View {
if let court = tournamentClub.courts.first(where: { $0.index == index }) {
LabeledContent {
if let name = court.name {
Text(name)
FooterButtonView("personnaliser") {
selectedCourt = court
}
} label: {
Text(court.courtIndexTitle())
Text(court.courtTitle())
HStack {
if court.indoor {
Text("Couvert")

@ -27,7 +27,7 @@ struct TournamentMatchFormatsSettingsView: View {
Section {
LabeledContent {
StepperView(title: "minutes", count: $tournament.additionalEstimationDuration, step: 5)
StepperView(title: "minutes", count: $tournament.additionalEstimationDuration, step: 5, minimum: -10)
} label: {
Text("Modifier les durées moyennes")
}

@ -374,7 +374,13 @@ struct InscriptionManagerView: View {
TipView(pasteTip) { action in
if let paste = UIPasteboard.general.string {
self.pasteString = paste
Task {
await MainActor.run {
fetchPlayers.nsPredicate = _pastePredicate(pasteField: paste, mostRecentDate: SourceFileManager.shared.mostRecentDateAvailable)
pasteString = paste
autoSelect = true
}
}
}
}
.tipStyle(tint: nil)

@ -25,6 +25,16 @@ struct TournamentInitView: View {
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 {

@ -72,15 +72,6 @@ struct TournamentView: View {
}
case .initial:
TournamentInitView()
NavigationLink(value: Screen.broadcast) {
LabeledContent {
Text(tournament.publishManually ? "manuel" : "auto.")
} label: {
Text("Publication")
}
}
case .build:
TournamentRunningView(tournament: tournament)
@ -153,7 +144,7 @@ struct TournamentView: View {
Text("Classement")
}
NavigationLink(value: Screen.broadcast) {
Text("Diffusion")
Text("Publication")
}
}
} label: {

Loading…
Cancel
Save