minor updates

sync2
Raz 1 year ago
parent 913d3de4f5
commit 0a816b20e1
  1. 5
      PadelClub/Data/PlayerRegistration.swift
  2. 4
      PadelClub/Data/Tournament.swift
  3. 2
      PadelClub/PadelClubApp.swift
  4. 15
      PadelClub/Utils/LocationManager.swift
  5. 23
      PadelClub/Utils/Tips.swift
  6. 10
      PadelClub/ViewModel/AgendaDestination.swift
  7. 33
      PadelClub/ViewModel/Selectable.swift
  8. 4
      PadelClub/Views/Components/GenericDestinationPickerView.swift
  9. 60
      PadelClub/Views/Navigation/Agenda/TournamentLookUpView.swift
  10. 2
      PadelClub/Views/Planning/PlanningSettingsView.swift
  11. 2
      PadelClub/Views/Tournament/TournamentView.swift

@ -283,6 +283,11 @@ final class PlayerRegistration: ModelObject, Storable {
}
func setComputedRank(in tournament: Tournament) {
if tournament.isAnimation() {
computedRank = rank ?? 0
return
}
let currentRank = rank ?? tournament.unrankValue(for: isMalePlayer()) ?? 70_000
switch tournament.tournamentCategory {
case .men:

@ -1430,7 +1430,9 @@ defer {
func formattedDate(_ displayStyle: DisplayStyle = .wide) -> String {
switch displayStyle {
case .wide, .title:
case .title:
startDate.formatted(.dateTime.weekday(.abbreviated).day().month(.abbreviated).year())
case .wide:
startDate.formatted(date: Date.FormatStyle.DateStyle.complete, time: Date.FormatStyle.TimeStyle.omitted)
case .short:
startDate.formatted(date: .numeric, time: .omitted)

@ -100,7 +100,7 @@ print("Running in Release mode")
//try? Tips.resetDatastore()
try? Tips.configure([
.displayFrequency(.immediate),
.displayFrequency(.daily),
.datastoreLocation(.applicationDefault)
])
}

@ -16,7 +16,18 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var postalCode: String?
@Published var requestStarted: Bool = false
@Published var userReadableCityOrZipcode: String = ""
@Published var lastError: Error? = nil
@Published var lastError: LocalizedError? = nil
enum LocationError: LocalizedError {
case unknownError(error: Error)
var errorDescription: String? {
switch self {
case .unknownError(let error):
return "Padel Club n'a pas réussi à vous localiser."
}
}
}
override init() {
super.init()
@ -49,7 +60,7 @@ class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("locationManager didFailWithError", error)
requestStarted = false
self.lastError = error
self.lastError = LocationError.unknownError(error: error)
}
func geocodeCity(cityOrZipcode: String, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {

@ -549,6 +549,29 @@ struct TeamsExportTip: Tip {
}
}
struct PlayerTournamentSearchTip: Tip {
var title: Text {
Text("Cherchez un tournoi autour de vous !")
}
var message: Text? {
Text("Padel Club facilite la recherche de tournois et l'inscription !")
}
var image: Image? {
Image(systemName: "trophy.circle")
}
var actions: [Action] {
Action(id: ActionKey.selectAction.rawValue, title: "Éssayer")
}
enum ActionKey: String {
case selectAction = "selectAction"
}
}
struct TipStyleModifier: ViewModifier {
@Environment(\.colorScheme) var colorScheme
var tint: Color?

@ -7,6 +7,7 @@
import Foundation
import SwiftUI
import TipKit
enum AgendaDestination: Int, CaseIterable, Identifiable, Selectable, Equatable {
var id: Int { self.rawValue }
@ -33,6 +34,15 @@ enum AgendaDestination: Int, CaseIterable, Identifiable, Selectable, Equatable {
}
}
func associatedTip() -> (any Tip)? {
switch self {
case .around:
return PlayerTournamentSearchTip()
default:
return nil
}
}
func selectionLabel(index: Int) -> String {
localizedTitleKey
}

@ -7,6 +7,7 @@
import Foundation
import SwiftUI
import TipKit
protocol Selectable {
func selectionLabel(index: Int) -> String
@ -15,9 +16,14 @@ protocol Selectable {
func badgeValueColor() -> Color?
func displayImageIfValueZero() -> Bool
func systemImage() -> String?
func associatedTip() -> (any Tip)?
}
extension Selectable {
func associatedTip() -> (any Tip)? {
return nil
}
func systemImage() -> String? {
return nil
}
@ -54,3 +60,30 @@ enum Badge {
}
}
}
struct SelectionTipViewModifier: ViewModifier {
let selectable: Selectable
let action: () -> Void
func body(content: Content) -> some View {
if let tip = selectable.associatedTip() {
if #available(iOS 18.0, *) {
content
.popoverTip(tip, arrowEdge: .top) { _ in
action()
tip.invalidate(reason: .tipClosed)
}
} else {
content
}
} else {
content
}
}
}
extension View {
func selectableTipViewModifier(selectable: Selectable, action: @escaping () -> Void) -> some View {
modifier(SelectionTipViewModifier(selectable: selectable, action: action))
}
}

@ -6,6 +6,7 @@
//
import SwiftUI
import TipKit
struct GenericDestinationPickerView<T: Identifiable & Selectable & Equatable >: View {
@EnvironmentObject var dataStore: DataStore
@ -49,6 +50,9 @@ struct GenericDestinationPickerView<T: Identifiable & Selectable & Equatable >:
.contentShape(Capsule())
}
}
.selectableTipViewModifier(selectable: destination) {
selectedDestination = destination
}
.padding()
.background {
Capsule()

@ -23,15 +23,44 @@ struct TournamentLookUpView: View {
@State private var requestedToGetAllPages: Bool = false
@State private var revealSearchParameters: Bool = true
@State private var presentAlert: Bool = false
@State private var confirmSearch: Bool = false
var tournaments: [FederalTournament] {
federalDataViewModel.searchedFederalTournaments
}
var showLastError: Binding<Bool> {
Binding {
locationManager.lastError != nil
} set: { value in
if value == false {
locationManager.lastError = nil
}
}
}
var body: some View {
List {
searchParametersView
}
.alert(isPresented: showLastError, error: locationManager.lastError as? LocationManager.LocationError, actions: {
Button("Annuler", role: .cancel) {
}
})
.confirmationDialog("Attention", isPresented: $confirmSearch, titleVisibility: .visible) {
Button("Cherchez quand même") {
requestedToGetAllPages = true
runSearch()
}
Button("Annuler", role: .cancel) {
}
} message: {
Text("Aucune ville n'a été indiqué, il est préférable de se localiser ou d'indiquer une ville pour réduire le nombre de résultat.")
}
.alert("Attention", isPresented: $presentAlert, actions: {
Button {
presentAlert = false
@ -70,7 +99,11 @@ struct TournamentLookUpView: View {
ToolbarItem(placement: .bottomBar) {
if revealSearchParameters {
FooterButtonView("Lancer la recherche") {
runSearch()
if dataStore.appSettings.city.isEmpty {
confirmSearch = true
} else {
runSearch()
}
}
.disabled(searching)
} else if searching {
@ -230,31 +263,6 @@ struct TournamentLookUpView: View {
}
}
@ViewBuilder
var searchContollerView: some View {
Section {
Button {
runSearch()
} label: {
HStack {
Label("Chercher un tournoi", systemImage: "magnifyingglass")
if searching {
Spacer()
ProgressView()
}
}
}
Button {
dataStore.appSettings.resetSearch()
locationManager.location = nil
locationManager.city = nil
revealSearchParameters = true
} label: {
Label("Ré-initialiser la recherche", systemImage: "xmark.circle")
}
}
}
@ViewBuilder
var searchParametersView: some View {
@Bindable var appSettings = dataStore.appSettings

@ -52,7 +52,7 @@ struct PlanningSettingsView: View {
Section {
DatePicker(selection: $tournament.startDate) {
Text(tournament.startDate.formatted(.dateTime.weekday(.wide)).capitalized)
Text(tournament.startDate.formatted(.dateTime.weekday(.wide)).capitalized).lineLimit(1)
}
LabeledContent {
StepperView(count: $tournament.dayDuration, minimum: 1)

@ -141,7 +141,7 @@ struct TournamentView: View {
ToolbarItem(placement: .principal) {
VStack(spacing: -4.0) {
Text(tournament.tournamentTitle(.title)).font(.headline)
Text(tournament.formattedDate())
Text(tournament.formattedDate(.title))
.font(.subheadline).foregroundStyle(.secondary)
}
.popoverTip(tournamentSelectionTip)

Loading…
Cancel
Save