online_reg
Raz 10 months ago
parent d11af504b5
commit 15870383e0
  1. 10
      PadelClub/Data/PlayerRegistration.swift
  2. 4
      PadelClub/Data/Tournament.swift
  3. 24
      PadelClub/InscriptionLegendView.swift
  4. 8
      PadelClub/RegistrationInfoSheetView.swift
  5. 18
      PadelClub/Views/Player/PlayerDetailView.swift
  6. 2
      PadelClub/Views/Shared/DateMenuView.swift
  7. 97
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  8. 4
      PadelClub/Views/Team/EditingTeamView.swift
  9. 8
      PadelClub/Views/Team/TeamDetailView.swift
  10. 5
      PadelClub/Views/Team/TeamRowView.swift
  11. 3
      PadelClub/Views/Tournament/Screen/Components/TournamentCategorySettingsView.swift
  12. 2
      PadelClub/Views/Tournament/Screen/Components/TournamentGeneralSettingsView.swift
  13. 36
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  14. 4
      PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift
  15. 4
      PadelClub/Views/Tournament/TournamentView.swift

@ -45,11 +45,11 @@ final class PlayerRegistration: ModelObject, Storable {
func localizedSourceLabel() -> String { func localizedSourceLabel() -> String {
switch source { switch source {
case .frenchFederation, .onlineRegistration: case .frenchFederation, .onlineRegistration:
return "Via la base fédérale" return "base fédérale"
case .beachPadel: case .beachPadel:
return "Via le fichier beach-padel" return "beach-padel"
case nil: case nil:
return "Manuellement" return "créé par vous-même"
} }
} }
@ -233,6 +233,10 @@ final class PlayerRegistration: ModelObject, Storable {
source == .beachPadel source == .beachPadel
} }
func unrankedOrUnknown() -> Bool {
source == nil
}
func isValidLicenseNumber(year: Int) -> Bool { func isValidLicenseNumber(year: Int) -> Bool {
guard let licenceId else { return false } guard let licenceId else { return false }
guard licenceId.isLicenseNumber else { return false } guard licenceId.isLicenseNumber else { return false }

@ -2165,6 +2165,10 @@ defer {
} }
} }
func onlineRegistrationCanBeEnabled() -> Bool {
isAnimation() == false
}
func roundSmartMatchFormat(_ roundIndex: Int) -> MatchFormat { func roundSmartMatchFormat(_ roundIndex: Int) -> MatchFormat {
let format = tournamentLevel.federalFormatForBracketRound(roundIndex) let format = tournamentLevel.federalFormatForBracketRound(roundIndex)
if tournamentLevel == .p25 { return .superTie } if tournamentLevel == .p25 { return .superTie }

@ -13,38 +13,38 @@ struct InscriptionLegendView: View {
var body: some View { var body: some View {
NavigationView { NavigationView {
List { List {
Section {
Label("Inscrit en ligne", systemImage: "circle.fill").foregroundStyle(.green)
} footer: {
Text("Icône indiquant que le joueur s'est inscrit en ligne.")
}
Section { Section {
ForEach(RoundRule.colors.prefix(6).indices, id: \.self) { colorIndex in ForEach(RoundRule.colors.prefix(6).indices, id: \.self) { colorIndex in
Text("Équipe placée en \(RoundRule.roundName(fromRoundIndex: colorIndex))") Text("Équipe placée en \(RoundRule.roundName(fromRoundIndex: colorIndex))")
.listRowView(isActive: true, color: Color(uiColor: .init(fromHex: RoundRule.colors[colorIndex])), hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: Color(uiColor: .init(fromHex: RoundRule.colors[colorIndex])), hideColorVariation: true, alignment: .leading)
} }
} }
Section { Section {
Text("Équipe placée en poule") Text("Équipe placée en poule")
.listRowView(isActive: true, color: .blue, hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: .blue, hideColorVariation: true, alignment: .leading)
} }
Section { Section {
Text("Équipe estimée en tableau") Text("Équipe estimée en tableau")
.listRowView(isActive: true, color: .mint, hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: .mint, hideColorVariation: true, alignment: .leading)
Text("Équipe estimée en poule") Text("Équipe estimée en poule")
.listRowView(isActive: true, color: .cyan, hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: .cyan, hideColorVariation: true, alignment: .leading)
} }
Section { Section {
Text("Équipe en liste d'attente") Text("Équipe en liste d'attente")
.listRowView(isActive: true, color: .gray, hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: .gray, hideColorVariation: true, alignment: .leading)
Text("Équipe forfaite") Text("Équipe forfaite")
.listRowView(isActive: true, color: .logoRed, hideColorVariation: true, alignment: .trailing) .listRowView(isActive: true, color: .logoRed, hideColorVariation: true, alignment: .leading)
}
Section {
Label("Inscrit en ligne", systemImage: "person.badge.shield.checkmark.fill")
} footer: {
Text("Icône indiquant que le joueur s'est inscrit en ligne.")
} }
Section { Section {

@ -45,12 +45,6 @@ struct RegistrationInfoSheetView: View {
NavigationView { NavigationView {
ScrollView { ScrollView {
VStack(alignment: .leading, spacing: 20) { VStack(alignment: .leading, spacing: 20) {
// Title
Text("Inscriptions en ligne")
.font(.title)
.fontWeight(.bold)
.padding(.bottom, 5)
// Content sections // Content sections
ForEach(registrationInfoText.components(separatedBy: "\n\n"), id: \.self) { section in ForEach(registrationInfoText.components(separatedBy: "\n\n"), id: \.self) { section in
if !section.isEmpty { if !section.isEmpty {
@ -84,6 +78,8 @@ struct RegistrationInfoSheetView: View {
.navigationBarItems(trailing: Button("Fermer") { .navigationBarItems(trailing: Button("Fermer") {
dismiss() dismiss()
}) })
.toolbarBackground(.visible, for: .navigationBar)
.navigationTitle("Inscription en ligne")
} }
} }
} }

@ -32,6 +32,22 @@ struct PlayerDetailView: View {
var body: some View { var body: some View {
Form { Form {
Section {
Text(player.localizedSourceLabel().firstCapitalized)
} header: {
Text("Source des informations")
}
if tournament.enableOnlineRegistration {
Section {
LabeledContent {
Text(player.registeredOnline ? "Oui" : "Non")
} label: {
Text("Inscription en ligne")
}
}
}
Section { Section {
Toggle("Joueur sur place", isOn: $player.hasArrived) Toggle("Joueur sur place", isOn: $player.hasArrived)
Toggle("Capitaine", isOn: $player.captain) Toggle("Capitaine", isOn: $player.captain)
@ -70,8 +86,6 @@ struct PlayerDetailView: View {
if let birthdate = player.birthdate { if let birthdate = player.birthdate {
Text(birthdate) Text(birthdate)
} }
} footer: {
Text(player.localizedSourceLabel())
} }
Section { Section {

@ -26,7 +26,7 @@ struct DateMenuView: View {
Button("24h après") { adjustDate(byDays: 1) } Button("24h après") { adjustDate(byDays: 1) }
Button("48h après") { adjustDate(byDays: 2) } Button("48h après") { adjustDate(byDays: 2) }
} label: { } label: {
Text("Ajuster la date") Text("Ajuster")
.underline() .underline()
} }
} }

@ -379,102 +379,7 @@ struct MySearchView: View {
let array = Array(searchViewModel.selectedPlayers) let array = Array(searchViewModel.selectedPlayers)
Section { Section {
ForEach(array) { player in ForEach(array) { player in
let index : Int? = nil ImportedPlayerView(player: player, index: nil, showFemaleInMaleAssimilation: searchViewModel.showFemaleInMaleAssimilation, showProgression: true)
VStack(alignment: .leading) {
HStack {
if player.isAnonymous() {
Text("Joueur Anonyme")
} else {
Text(player.getLastName().capitalized)
Text(player.getFirstName().capitalized)
}
if index == nil {
Text(player.male ? "" : "")
}
Spacer()
if let index {
HStack(alignment: .top, spacing: 0) {
Text(index.formatted())
.foregroundStyle(.secondary)
.font(.title3)
Text(index.ordinalFormattedSuffix())
.foregroundStyle(.secondary)
.font(.caption)
}
}
}
.font(.title3)
.lineLimit(1)
HStack {
HStack(alignment: .top, spacing: 0) {
Text(player.formattedRank()).italic(player.isAssimilated)
.font(.title3)
.background {
if player.isNotFromCurrentDate() {
UnderlineView()
}
}
if let rank = player.getRank() {
Text(rank.ordinalFormattedSuffix()).italic(player.isAssimilated)
.font(.caption)
}
}
if showProgression, player.getProgression() != 0 {
HStack(alignment: .top, spacing: 2) {
Text("(")
Text(player.getProgression().formatted(.number.sign(strategy: .always())))
.foregroundStyle(player.getProgressionColor(progression: player.getProgression()))
Text(")")
}.font(.title3)
}
if let pts = player.getPoints(), pts > 0 {
HStack(alignment: .lastTextBaseline, spacing: 0) {
Text(pts.formatted()).font(.title3)
Text(" pts").font(.caption)
}
}
if let tournamentPlayed = player.tournamentPlayed, tournamentPlayed > 0 {
HStack(alignment: .lastTextBaseline, spacing: 0) {
Text(tournamentPlayed.formatted()).font(.title3)
Text(" tournoi" + tournamentPlayed.pluralSuffix).font(.caption)
}
}
}
.lineLimit(1)
.truncationMode(.tail)
if showFemaleInMaleAssimilation, let assimilatedAsMaleRank = player.getAssimilatedAsMaleRank() {
HStack(alignment: .top, spacing: 2) {
Text("(")
Text(assimilatedAsMaleRank.formatted())
VStack(alignment: .leading, spacing: 0) {
Text("équivalence")
Text("messieurs")
}
.font(.caption)
Text(")").font(.title3)
}
}
HStack {
Text(player.formattedLicense())
if let computedAge = player.computedAge {
Text(computedAge.formatted() + " ans")
}
}
.font(.caption)
if let clubName = player.clubName {
Text(clubName)
.font(.caption)
}
if let ligueName = player.ligueName {
Text(ligueName)
.font(.caption)
}
}
} }
.onDelete { indexSet in .onDelete { indexSet in
for index in indexSet { for index in indexSet {

@ -65,15 +65,13 @@ struct EditingTeamView: View {
var body: some View { var body: some View {
List { List {
Section { Section {
RowButtonView("Modifier la composition de l'équipe", role: team.hasRegisteredOnline() ? .destructive : .none) { RowButtonView("Modifier la composition de l'équipe", role: team.hasRegisteredOnline() ? .destructive : .none, confirmationMessage: "Vous êtes sur le point de modifier une équipe qui s'est inscrite en ligne.") {
editedTeam = team editedTeam = team
} }
TeamDetailView(team: team) TeamDetailView(team: team)
} header: { } header: {
if team.hasRegisteredOnline() { if team.hasRegisteredOnline() {
Text("Inscription en ligne") Text("Inscription en ligne")
.foregroundStyle(.master)
} else { } else {
Text("Inscription par vous-même") Text("Inscription par vous-même")
} }

@ -22,12 +22,20 @@ struct TeamDetailView: View {
PlayerDetailView(player: player) PlayerDetailView(player: player)
.environment(tournament) .environment(tournament)
} label: { } label: {
VStack(alignment: .leading, spacing: 0) {
HStack {
Text("inscrit en ligne")
Spacer()
Text(player.localizedSourceLabel())
}
.font(.caption).foregroundStyle(.secondary)
PlayerView(player: player) PlayerView(player: player)
} }
} }
} }
} }
} }
}
//#Preview { //#Preview {
// TeamDetailView(team: TeamRegistration.mock()) // TeamDetailView(team: TeamRegistration.mock())

@ -118,9 +118,10 @@ struct TeamRowView: View {
var body: some View { var body: some View {
ForEach(team.players()) { player in ForEach(team.players()) { player in
HStack { HStack(spacing: 4) {
if player.registeredOnline { if player.registeredOnline {
Image(systemName: "person.badge.shield.checkmark.fill") Image(systemName: "circle.fill").foregroundStyle(.green)
.font(.system(size: 8))
} }
Text(player.playerLabel()).lineLimit(1).truncationMode(.tail) Text(player.playerLabel()).lineLimit(1).truncationMode(.tail)
} }

@ -36,6 +36,9 @@ struct TournamentCategorySettingsView: View {
private func _save() { private func _save() {
do { do {
if tournament.onlineRegistrationCanBeEnabled() == false, tournament.enableOnlineRegistration {
tournament.enableOnlineRegistration = false
}
try dataStore.tournaments.addOrUpdate(instance: tournament) try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch { } catch {
Logger.error(error) Logger.error(error)

@ -48,6 +48,7 @@ struct TournamentGeneralSettingsView: View {
Text("Si vous souhaitez que Padel Club vous aide à suivre les encaissements, indiquer un prix d'inscription. Sinon Padel Club vous aidera à suivre simplement l'arrivée et la présence des joueurs.") Text("Si vous souhaitez que Padel Club vous aide à suivre les encaissements, indiquer un prix d'inscription. Sinon Padel Club vous aidera à suivre simplement l'arrivée et la présence des joueurs.")
} }
if tournament.onlineRegistrationCanBeEnabled() {
Section { Section {
NavigationLink { NavigationLink {
RegistrationSetupView(tournament: tournament) RegistrationSetupView(tournament: tournament)
@ -70,6 +71,7 @@ struct TournamentGeneralSettingsView: View {
} footer: { } footer: {
Text("Paramétrez les possibilités d'inscription en ligne à votre tournoi via Padel Club") Text("Paramétrez les possibilités d'inscription en ligne à votre tournoi via Padel Club")
} }
}
Section { Section {
TextField("Nom du tournoi", text: $tournamentName, axis: .vertical) TextField("Nom du tournoi", text: $tournamentName, axis: .vertical)

@ -250,7 +250,7 @@ struct InscriptionManagerView: View {
RowButtonView("Rafraîchir la liste") { RowButtonView("Rafraîchir la liste") {
await _refreshList() await _refreshList()
} }
} else { } else if tournament.onlineRegistrationCanBeEnabled() {
RowButtonView("Inscription en ligne") { RowButtonView("Inscription en ligne") {
navigation.path.append(Screen.settings) navigation.path.append(Screen.settings)
} }
@ -533,19 +533,19 @@ struct InscriptionManagerView: View {
} }
} }
private func _fixModel() { // private func _fixModel() {
let players = tournament.players() // let players = tournament.players()
//
players.forEach { player in // players.forEach { player in
if player.source == .onlineRegistration { // if player.source == .onlineRegistration {
player.source = .frenchFederation // player.source = .frenchFederation
player.registeredOnline = true // player.registeredOnline = true
} // }
} // }
//
try? tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players) // try? tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players)
} // }
//
private func _refreshList() async { private func _refreshList() async {
if refreshInProgress { return } if refreshInProgress { return }
@ -629,7 +629,7 @@ struct InscriptionManagerView: View {
_teamDeleteButtonView(team) _teamDeleteButtonView(team)
} }
} }
.listRowView(isActive: true, color: team.initialRoundColor() ?? tournament.cutLabelColor(index: teamIndex, teamCount: filterMode == .waiting ? 0 : selectedSortedTeams.count), hideColorVariation: true, backgroundColor: color, alignment: .trailing) .listRowView(isActive: true, color: team.initialRoundColor() ?? tournament.cutLabelColor(index: teamIndex, teamCount: filterMode == .waiting ? 0 : selectedSortedTeams.count), hideColorVariation: true, backgroundColor: color, alignment: .leading)
} }
} header: { } header: {
if filterMode == .all && walkoutTeams.isEmpty == false { if filterMode == .all && walkoutTeams.isEmpty == false {
@ -837,9 +837,9 @@ struct InscriptionManagerView: View {
CloseDatePicker(closedRegistrationDate: closedRegistrationDate) CloseDatePicker(closedRegistrationDate: closedRegistrationDate)
} }
Button("bug fix") { // Button("bug fix") {
_fixModel() // _fixModel()
} // }
if tournament.enableOnlineRegistration { if tournament.enableOnlineRegistration {
Button { Button {

@ -114,7 +114,7 @@ struct RegistrationSetupView: View {
} }
if openingRegistrationDateEnabled { if openingRegistrationDateEnabled {
DatePicker(selection: $openingRegistrationDate, in: tournament.creationDate.truncateMinutesAndSeconds()...tournament.startDate.truncateMinutesAndSeconds()) { DatePicker(selection: $openingRegistrationDate) {
DateMenuView(date: $openingRegistrationDate) DateMenuView(date: $openingRegistrationDate)
} }
} }
@ -130,7 +130,7 @@ struct RegistrationSetupView: View {
} }
if registrationDateLimitEnabled { if registrationDateLimitEnabled {
DatePicker(selection: $registrationDateLimit, in: tournament.creationDate.truncateMinutesAndSeconds()...tournament.startDate.truncateMinutesAndSeconds()) { DatePicker(selection: $registrationDateLimit) {
DateMenuView(date: $registrationDateLimit) DateMenuView(date: $registrationDateLimit)
} }
} }

@ -63,7 +63,7 @@ struct TournamentView: View {
} }
} }
case .initial: case .initial:
if tournament.enableOnlineRegistration == false { if tournament.enableOnlineRegistration == false, tournament.onlineRegistrationCanBeEnabled() {
TipView(onlineRegistrationTip) { action in TipView(onlineRegistrationTip) { action in
if let actionKey = OnlineRegistrationTip.ActionKey(rawValue: action.id) { if let actionKey = OnlineRegistrationTip.ActionKey(rawValue: action.id) {
switch actionKey { switch actionKey {
@ -84,7 +84,7 @@ struct TournamentView: View {
} }
TournamentInitView(tournament: tournament) TournamentInitView(tournament: tournament)
case .build: case .build:
if tournament.enableOnlineRegistration == false { if tournament.enableOnlineRegistration == false, tournament.onlineRegistrationCanBeEnabled() {
TipView(onlineRegistrationTip) { action in TipView(onlineRegistrationTip) { action in
if let actionKey = OnlineRegistrationTip.ActionKey(rawValue: action.id) { if let actionKey = OnlineRegistrationTip.ActionKey(rawValue: action.id) {
switch actionKey { switch actionKey {

Loading…
Cancel
Save