multistore
Razmig Sarkissian 2 years ago
parent f06a54cc67
commit 18c744b34a
  1. 3
      PadelClub/ViewModel/SearchViewModel.swift
  2. 10
      PadelClub/Views/Navigation/MainView.swift
  3. 63
      PadelClub/Views/Player/Components/PlayerPopoverView.swift
  4. 32
      PadelClub/Views/Shared/SelectablePlayerListView.swift
  5. 54
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift

@ -27,7 +27,8 @@ class SearchViewModel: ObservableObject, Identifiable {
@Published var sortOption: SortOption = .rank
@Published var selectedPlayers: Set<ImportedPlayer> = Set()
@Published var filterSelectionEnabled: Bool = false
var forcedSearch = false
@Published var isPresented: Bool = false
var mostRecentDate: Date? = nil
var selectionIsOver: Bool {

@ -48,11 +48,11 @@ struct MainView: View {
await self._checkSourceFileAvailability()
await self._downloadPreviousDate()
}
.refreshable {
Task {
await self._checkSourceFileAvailability()
}
}
// .refreshable {
// Task {
// await self._checkSourceFileAvailability()
// }
// }
.overlay(alignment: .bottom) {
if importingFiles {
_activityStatusBoxView()

@ -29,10 +29,10 @@ struct PlayerPopoverView: View {
@FocusState private var licenseIsFocused: Bool
@FocusState private var amountIsFocused: Bool
static var source: String?
init(sex: Int, requiredField: [PlayerCreationField] = [.firstName, .lastName], creationCompletionHandler: @escaping (PlayerRegistration) -> Void) {
let source = PlayerPopoverView.source
@State private var source: String?
init(source: String?, sex: Int, requiredField: [PlayerCreationField] = [.firstName, .lastName], creationCompletionHandler: @escaping (PlayerRegistration) -> Void) {
let source = source
if let source {
let words = source.components(separatedBy: .whitespaces)
if words.isEmpty == false {
@ -51,29 +51,28 @@ struct PlayerPopoverView: View {
self.requiredField = requiredField
self.creationCompletionHandler = creationCompletionHandler
self.pasteBoard = UIPasteboard.general.string
_source = State(wrappedValue: source)
}
@State private var pasteBoard: String?
var body: some View {
NavigationStack {
List {
if let pasteBoard {
if let source {
Section {
Text(pasteBoard).foregroundColor(.clear).padding(8)
Text(source).foregroundColor(.clear).padding(8)
.frame(maxWidth: .infinity)
.overlay(
TextEditor(text: .constant(pasteBoard))
TextEditor(text: .constant(source))
)
.frame(minHeight: 20.0)
} header: {
HStack {
Spacer()
Button {
self.pasteBoard = ""
Button(role: .cancel) {
self.source = nil
} label: {
Text("effacer le contenu du presse-papier")
.font(.caption)
}
.buttonStyle(.borderless)
}
@ -95,6 +94,8 @@ struct PlayerPopoverView: View {
Spacer()
TextField("Prénom", text: $firstName)
.submitLabel(.next)
.keyboardType(.alphabet)
.textInputAutocapitalization(.words)
.focused($firstNameIsFocused)
.onSubmit {
firstName = firstName.trimmed
@ -106,8 +107,10 @@ struct PlayerPopoverView: View {
Text("Nom").foregroundStyle(.secondary)
Spacer()
TextField("Nom", text: $lastName)
.focused($lastNameIsFocused)
.submitLabel(.next)
.textInputAutocapitalization(.words)
.keyboardType(.alphabet)
.focused($lastNameIsFocused)
.onSubmit {
lastName = lastName.trimmed
licenseIsFocused = true
@ -119,7 +122,8 @@ struct PlayerPopoverView: View {
Spacer()
TextField("Licence", text: $license)
.focused($licenseIsFocused)
.keyboardType(.namePhonePad)
.textInputAutocapitalization(.never)
.keyboardType(.numberPad)
.submitLabel(.next)
.onSubmit {
license = license.trimmed
@ -138,21 +142,23 @@ struct PlayerPopoverView: View {
HStack {
Text("Rang").foregroundStyle(.secondary)
Spacer()
TextField("Non classé", value: $rank, format: .number)
TextField("Non Classé" + (sex == 1 ? "" : "e"), value: $rank, format: .number)
.focused($amountIsFocused)
.keyboardType(.asciiCapable)
.textInputAutocapitalization(.never)
.keyboardType(.numberPad)
.submitLabel(.done)
.fixedSize()
}
} header: {
HStack {
Spacer()
Button {
Button(role: .cancel) {
let last = firstName
firstName = lastName
lastName = last
} label: {
Text("inverser nom & prénom")
.font(.caption)
}.buttonStyle(.borderless)
}
.textCase(nil)
@ -192,6 +198,27 @@ struct PlayerPopoverView: View {
dismiss()
}
}
if amountIsFocused || licenseIsFocused {
ToolbarItem(placement: .keyboard) {
Button("Confirmer") {
if licenseIsFocused {
license = license.trimmed
if requiredField.contains(.license) {
if license.isLicenseNumber {
amountIsFocused = true
} else {
displayWrongLicenceError = true
}
} else {
amountIsFocused = true
}
} else {
amountIsFocused = false
}
}
}
}
}
.alert("Attention", isPresented: $displayWrongLicenceError) {
Button("OK") {
@ -223,7 +250,7 @@ struct PlayerPopoverView: View {
}
#Preview {
PlayerPopoverView(sex: 1) { player in
PlayerPopoverView(source: "Razmig Sarkissian", sex: 1) { player in
}
}

@ -34,6 +34,7 @@ struct SelectablePlayerListView: View {
self.playerSelectionAction = playerSelectionAction
self.contentUnavailableAction = contentUnavailableAction
let searchViewModel = SearchViewModel()
searchViewModel.isPresented = allowSelection != 0
searchViewModel.user = user
searchViewModel.allowSelection = allowSelection
searchViewModel.codeClub = fromPlayer?.clubCode ?? codeClub
@ -65,9 +66,11 @@ struct SelectablePlayerListView: View {
}
MySearchView(searchViewModel: searchViewModel, contentUnavailableAction: contentUnavailableAction)
.environment(\.editMode, searchViewModel.allowMultipleSelection ? .constant(.active) : .constant(.inactive))
.searchable(text: $searchViewModel.debouncableText, tokens: $searchViewModel.tokens, suggestedTokens: $searchViewModel.suggestedTokens, placement: .navigationBarDrawer(displayMode: .always), prompt: searchViewModel.prompt(forDataSet: searchViewModel.dataSet), token: { token in
.searchable(text: $searchViewModel.debouncableText, tokens: $searchViewModel.tokens, suggestedTokens: $searchViewModel.suggestedTokens, isPresented: $searchViewModel.isPresented, placement: .navigationBarDrawer(displayMode: .always), prompt: searchViewModel.prompt(forDataSet: searchViewModel.dataSet), token: { token in
Text(token.shortLocalizedLabel)
})
.keyboardType(.alphabet)
.autocorrectionDisabled()
// .searchSuggestions({
// ForEach(searchViewModel.suggestedTokens) { token in
// Button {
@ -261,24 +264,6 @@ struct MySearchView: View {
.listStyle(.grouped)
.headerProminence(.increased)
.scrollDismissesKeyboard(.immediately)
.onChange(of: searchViewModel.searchText) {
search()
}
.onChange(of: searchViewModel.filterOption) {
search()
}
.onChange(of: searchViewModel.dataSet) {
search()
}
.onChange(of: searchViewModel.sortOption) {
sort()
}
.onChange(of: searchViewModel.ascending) {
sort()
}
.onChange(of: searchViewModel.hideAssimilation) {
search()
}
}
var specificBugFixUUID: String {
@ -311,6 +296,7 @@ struct MySearchView: View {
} header: {
Text(searchViewModel.selectedPlayers.count.formatted() + " " + searchViewModel.filterOption.localizedPlayerLabel + searchViewModel.selectedPlayers.count.pluralSuffix)
}
} else if (searchViewModel.isPresented == true && searchViewModel.dataSet == .national && searchViewModel.searchText.isEmpty == true) {
} else {
Section {
ForEach(players, id: \.self) { player in
@ -455,12 +441,4 @@ struct MySearchView: View {
}
}
}
private func search() {
//players.nsPredicate = searchViewModel.predicate()
}
private func sort() {
//players.nsSortDescriptors = searchViewModel.nsSortDescriptors()
}
}

@ -23,13 +23,14 @@ struct InscriptionManagerView: View {
@State private var presentPlayerCreation: Bool = false
@State private var presentImportView: Bool = false
@State private var createdPlayers: Set<PlayerRegistration> = Set()
@State private var testCreatedPlayers: Set<String> = Set()
@State private var createdPlayerIds: Set<String> = Set()
@State private var editedTeam: TeamRegistration?
@State private var pasteString: String?
@State private var currentRankSourceDate: Date?
@State private var confirmUpdateRank = false
@State private var updatingRank = false
@State private var selectionSearchField: String?
let slideToDeleteTip = SlideToDeleteTip()
let inscriptionManagerWomanRankTip = InscriptionManagerWomanRankTip()
let fileTip = InscriptionManagerFileInputTip()
@ -54,6 +55,10 @@ struct InscriptionManagerView: View {
}
}
private func _searchSource() -> String? {
selectionSearchField ?? pasteString
}
private func _pastePredicate(pasteField: String, mostRecentDate: Date?) -> NSPredicate? {
let text = pasteField.canonicalVersion
@ -95,7 +100,7 @@ struct InscriptionManagerView: View {
private func _currentSelection() -> Set<PlayerRegistration> {
var currentSelection = Set<PlayerRegistration>()
testCreatedPlayers.compactMap { id in
createdPlayerIds.compactMap { id in
fetchPlayers.first(where: { id == $0.license })
}.forEach { player in
let player = PlayerRegistration(importedPlayer: player)
@ -103,7 +108,7 @@ struct InscriptionManagerView: View {
currentSelection.insert(player)
}
testCreatedPlayers.compactMap { id in
createdPlayerIds.compactMap { id in
createdPlayers.first(where: { id == $0.id })
}.forEach {
currentSelection.insert($0)
@ -114,22 +119,22 @@ struct InscriptionManagerView: View {
private func _createTeam() {
tournament.addTeam(_currentSelection())
createdPlayers.removeAll()
testCreatedPlayers.removeAll()
createdPlayerIds.removeAll()
pasteString = nil
}
private func _updateTeam() {
editedTeam?.updatePlayers(_currentSelection())
createdPlayers.removeAll()
testCreatedPlayers.removeAll()
createdPlayerIds.removeAll()
pasteString = nil
editedTeam = nil
}
private func _buildingTeamView() -> some View {
List(selection: $testCreatedPlayers) {
List(selection: $createdPlayerIds) {
Section {
ForEach(testCreatedPlayers.sorted(), id: \.self) { id in
ForEach(createdPlayerIds.sorted(), id: \.self) { id in
if let p = createdPlayers.first(where: { $0.id == id }) {
PlayerView(player: p).tag(p.id)
}
@ -143,7 +148,7 @@ struct InscriptionManagerView: View {
}
if editedTeam == nil {
if testCreatedPlayers.isEmpty {
if createdPlayerIds.isEmpty {
RowButtonView(title: "Bloquer une place") {
_createTeam()
}
@ -169,7 +174,7 @@ struct InscriptionManagerView: View {
Button("effacer", role: .destructive) {
self.pasteString = nil
self.createdPlayers.removeAll()
self.testCreatedPlayers.removeAll()
self.createdPlayerIds.removeAll()
}
.buttonStyle(.borderless)
}
@ -204,7 +209,7 @@ struct InscriptionManagerView: View {
.onReceive(fetchPlayers.publisher.count()) { _ in // <-- here
if let pasteString, count == 2 {
fetchPlayers.filter { $0.hitForSearch(pasteString) >= hitTarget }.sorted(by: { $0.hitForSearch(pasteString) > $1.hitForSearch(pasteString) }).forEach { player in
testCreatedPlayers.insert(player.license!)
createdPlayerIds.insert(player.license!)
}
}
}
@ -307,7 +312,7 @@ struct InscriptionManagerView: View {
editedTeam = team
team.unsortedPlayers().forEach { player in
createdPlayers.insert(player)
testCreatedPlayers.insert(player.id)
createdPlayerIds.insert(player.id)
}
}
Divider()
@ -325,12 +330,14 @@ struct InscriptionManagerView: View {
}
}
.searchable(text: $searchField, isPresented: $presentSearch, prompt: Text("Chercher parmi les équipes inscrites"))
.keyboardType(.alphabet)
.autocorrectionDisabled()
}
var body: some View {
VStack(spacing: 0) {
_managementView()
if testCreatedPlayers.isEmpty == false || pasteString != nil || editedTeam != nil {
if createdPlayerIds.isEmpty == false || pasteString != nil || editedTeam != nil {
_buildingTeamView()
} else if tournament.unsortedTeams().isEmpty {
_inscriptionTipsView()
@ -338,22 +345,29 @@ struct InscriptionManagerView: View {
_teamRegisteredView()
}
}
.sheet(isPresented: $presentPlayerSearch) {
.sheet(isPresented: $presentPlayerSearch, onDismiss: {
selectionSearchField = nil
}) {
NavigationStack {
SelectablePlayerListView(allowSelection: -1, filterOption: _filterOption()) { players in
selectionSearchField = nil
players.forEach { player in
let newPlayer = PlayerRegistration(importedPlayer: player)
newPlayer.setWeight(in: tournament)
createdPlayers.insert(newPlayer)
testCreatedPlayers.insert(newPlayer.id)
createdPlayerIds.insert(newPlayer.id)
}
} contentUnavailableAction: { searchViewModel in
selectionSearchField = searchViewModel.searchText
presentPlayerSearch = false
presentPlayerCreation = true
}
}
}
.sheet(isPresented: $presentPlayerCreation) {
PlayerPopoverView(sex: _addPlayerSex()) { p in
PlayerPopoverView(source: _searchSource(), sex: _addPlayerSex()) { p in
createdPlayers.insert(p)
testCreatedPlayers.insert(p.id)
createdPlayerIds.insert(p.id)
}
}
.sheet(isPresented: $presentImportView) {
@ -374,11 +388,11 @@ struct InscriptionManagerView: View {
}
.toolbar {
if testCreatedPlayers.isEmpty == false {
if createdPlayerIds.isEmpty == false {
ToolbarItem(placement: .cancellationAction) {
Button("Annuler", role: .cancel) {
createdPlayers.removeAll()
testCreatedPlayers.removeAll()
createdPlayerIds.removeAll()
}
}
}
@ -443,7 +457,7 @@ struct InscriptionManagerView: View {
}
}
}
.navigationBarBackButtonHidden(testCreatedPlayers.isEmpty == false)
.navigationBarBackButtonHidden(createdPlayerIds.isEmpty == false)
.toolbarBackground(.visible, for: .navigationBar)
.navigationTitle("Inscriptions")
.navigationBarTitleDisplayMode(.inline)

Loading…
Cancel
Save