You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
12 KiB
304 lines
12 KiB
//
|
|
// ClubDetailView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 20/03/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LeStorage
|
|
|
|
struct ClubDetailView: View {
|
|
@EnvironmentObject var dataStore: DataStore
|
|
@Environment(\.dismiss) var dismiss
|
|
@FocusState var focusedField: Club.CodingKeys?
|
|
@State private var acronymMode: Club.AcronymMode = .automatic
|
|
@State private var city: String
|
|
@State private var zipCode: String
|
|
@State private var selectedCourt: Court?
|
|
@Bindable var club: Club
|
|
@State private var clubDeleted: Bool = false
|
|
@State private var confirmDeletion: Bool = false
|
|
@State private var timezone: String = TimeZone.current.identifier
|
|
|
|
var displayContext: DisplayContext
|
|
var selection: ((Club) -> ())? = nil
|
|
|
|
init(club: Club, displayContext: DisplayContext, selection: ((Club) -> ())? = nil) {
|
|
_club = Bindable(club)
|
|
self.displayContext = displayContext
|
|
self.selection = selection
|
|
_acronymMode = State(wrappedValue: club.shortNameMode())
|
|
_city = State(wrappedValue: club.city ?? "")
|
|
_zipCode = State(wrappedValue: club.zipCode ?? "")
|
|
|
|
if let timezone = club.timezone {
|
|
self.timezone = timezone
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
Form {
|
|
if displayContext == .edition || displayContext == .lockedForEditing {
|
|
let isFavorite = club.isFavorite()
|
|
Section {
|
|
RowButtonView(isFavorite ? "Retirer des favoris" : "Mettre en favori", role: isFavorite ? .destructive : nil) {
|
|
if isFavorite {
|
|
dataStore.user.clubs.removeAll(where: { $0 == club.id })
|
|
} else {
|
|
dataStore.user.clubs.append(club.id)
|
|
}
|
|
self.dataStore.saveUser()
|
|
dismiss()
|
|
}
|
|
} footer: {
|
|
if displayContext == .lockedForEditing {
|
|
VStack(alignment: .leading) {
|
|
Text("Édition impossible, vous n'êtes pas le créateur de ce club.")
|
|
FooterButtonView("Contactez-nous") {
|
|
_openMail()
|
|
}
|
|
}
|
|
.font(.footnote)
|
|
.foregroundStyle(.logoRed)
|
|
}
|
|
}
|
|
}
|
|
|
|
Section {
|
|
TextField("Nom du club (4 lettres mini)", text: $club.name)
|
|
.autocorrectionDisabled()
|
|
.keyboardType(.alphabet)
|
|
.frame(maxWidth: .infinity)
|
|
.focused($focusedField, equals: ._name)
|
|
.submitLabel( displayContext == .addition ? .next : .done)
|
|
.onChange(of: club.name) {
|
|
if club.name.count > 50 {
|
|
club.name = String(club.name.prefix(50))
|
|
}
|
|
}
|
|
.onSubmit(of: .text) {
|
|
if club.acronym.isEmpty {
|
|
club.acronym = club.name.canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines).acronym()
|
|
}
|
|
|
|
if displayContext == .edition && city.isEmpty == true {
|
|
focusedField = ._city
|
|
} else {
|
|
focusedField = nil
|
|
}
|
|
|
|
}
|
|
.disabled(displayContext == .lockedForEditing)
|
|
|
|
LabeledContent {
|
|
if acronymMode == .automatic || displayContext == .lockedForEditing {
|
|
Text(club.acronym)
|
|
} else {
|
|
TextField("Nom court", text: $club.acronym)
|
|
.textInputAutocapitalization(.never)
|
|
.fixedSize()
|
|
.focused($focusedField, equals: ._acronym)
|
|
.submitLabel(.done)
|
|
.multilineTextAlignment(.trailing)
|
|
.onChange(of: club.acronym) {
|
|
if club.acronym.count > 10 {
|
|
club.acronym = String(club.acronym.prefix(10))
|
|
} else if club.acronym.count == 0 {
|
|
acronymMode = .automatic
|
|
}
|
|
}
|
|
}
|
|
} label: {
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
Text("Nom court (10 lettres max.)").foregroundStyle(.secondary).font(.caption)
|
|
Menu {
|
|
Section {
|
|
ForEach(Club.AcronymMode.allCases, id: \.self) { option in
|
|
Toggle(isOn: .init(get: {
|
|
acronymMode == option
|
|
}, set: { value in
|
|
acronymMode = option
|
|
})) {
|
|
Text(option.rawValue)
|
|
}
|
|
}
|
|
} header: {
|
|
Text("Nom court")
|
|
}
|
|
} label: {
|
|
Text(acronymMode.rawValue)
|
|
}
|
|
.disabled(displayContext == .lockedForEditing)
|
|
}
|
|
}
|
|
.onChange(of: acronymMode) {
|
|
focusedField = ._acronym
|
|
if acronymMode == .custom {
|
|
//club.acronym = ""
|
|
} else {
|
|
//club.acronym = club.automaticShortName().uppercased()
|
|
}
|
|
}
|
|
} footer: {
|
|
if displayContext != .lockedForEditing {
|
|
Text("Vous pouvez personaliser le nom court ou laisser celui généré par défaut.")
|
|
}
|
|
}
|
|
|
|
if club.code == nil {
|
|
Section {
|
|
LabeledContent {
|
|
TextField("Ville", text: $city)
|
|
.autocorrectionDisabled()
|
|
.keyboardType(.alphabet)
|
|
.multilineTextAlignment(.trailing)
|
|
.frame(maxWidth: .infinity)
|
|
.focused($focusedField, equals: ._city)
|
|
.submitLabel( displayContext == .addition ? .next : .done)
|
|
.onSubmit {
|
|
if displayContext == .addition {
|
|
focusedField = ._zipCode
|
|
}
|
|
}
|
|
} label: {
|
|
Text("Ville")
|
|
}
|
|
.onTapGesture {
|
|
focusedField = ._city
|
|
}
|
|
|
|
LabeledContent {
|
|
TextField("Code Postal", text: $zipCode)
|
|
.autocorrectionDisabled()
|
|
.keyboardType(.alphabet)
|
|
.multilineTextAlignment(.trailing)
|
|
.frame(maxWidth: .infinity)
|
|
.focused($focusedField, equals: ._zipCode)
|
|
.submitLabel( displayContext == .addition ? .next : .done)
|
|
} label: {
|
|
Text("Code Postal")
|
|
}
|
|
.onTapGesture {
|
|
focusedField = ._zipCode
|
|
}
|
|
}
|
|
.disabled(displayContext == .lockedForEditing)
|
|
}
|
|
|
|
let federalLink = club.federalLink()
|
|
let padelClubLink = club.shareURL()
|
|
if federalLink != nil || padelClubLink != nil {
|
|
Section {
|
|
if let federalLink {
|
|
LabeledContent("Code Club") {
|
|
Text(club.code ?? "")
|
|
}
|
|
LabeledContent("Ville") {
|
|
Text(club.city ?? "")
|
|
}
|
|
Link(destination: federalLink) {
|
|
Text("Accéder au club sur Tenup")
|
|
}
|
|
}
|
|
if let padelClubLink, club.creator != nil {
|
|
Link(destination: padelClubLink) {
|
|
Text("Accéder au club sur Padel Club")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ClubCourtSetupView(club: club, displayContext: displayContext, selectedCourt: $selectedCourt, hideLockForEditingMessage: true)
|
|
|
|
if displayContext == .edition {
|
|
Section {
|
|
RowButtonView("Supprimer ce club", role: .destructive) {
|
|
_deleteClub()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.navigationBarBackButtonHidden(focusedField != nil)
|
|
.toolbar(content: {
|
|
if focusedField != nil {
|
|
ToolbarItem(placement: .keyboard) {
|
|
HStack {
|
|
Button("Fermer", role: .cancel) {
|
|
focusedField = nil
|
|
}
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
})
|
|
.keyboardType(.alphabet)
|
|
.autocorrectionDisabled()
|
|
.defaultFocus($focusedField, ._name, priority: .automatic)
|
|
.navigationTitle(displayContext == .addition ? "Nouveau club" : "Détail du club")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar(.visible, for: .navigationBar)
|
|
.headerProminence(.increased)
|
|
.toolbarBackground(.visible, for: .navigationBar)
|
|
.navigationDestination(item: $selectedCourt) { court in
|
|
CourtView(court: court)
|
|
}
|
|
.onChange(of: zipCode) {
|
|
club.zipCode = zipCode
|
|
}
|
|
.onChange(of: city) {
|
|
club.city = city
|
|
}
|
|
.onDisappear {
|
|
if displayContext == .edition && clubDeleted == false {
|
|
dataStore.clubs.addOrUpdate(instance: club)
|
|
}
|
|
}
|
|
.onAppear {
|
|
if displayContext == .addition {
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
focusedField = ._name
|
|
}
|
|
}
|
|
}
|
|
.toolbar {
|
|
if displayContext == .edition {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Button(role: .destructive) {
|
|
confirmDeletion = true
|
|
} label: {
|
|
LabelDelete()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.confirmationDialog("Êtes-vous sûr de vouloir supprimer ce club ?", isPresented: $confirmDeletion, titleVisibility: .visible) {
|
|
Button("Oui, je suis sûr") {
|
|
_deleteClub()
|
|
}
|
|
|
|
Button("Annuler", role: .cancel) {
|
|
}
|
|
}
|
|
}
|
|
|
|
private func _openMail() {
|
|
let emailTo: String = "support@padelclub.app"
|
|
let subject: String = "Édition de club impossible : \(club.name)"
|
|
if let url = URL(string: "mailto:\(emailTo)?subject=\(subject)"), UIApplication.shared.canOpenURL(url) {
|
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
}
|
|
}
|
|
|
|
private func _deleteClub() {
|
|
clubDeleted = true
|
|
dataStore.user.clubs.removeAll(where: { $0 == club.id })
|
|
self.dataStore.saveUser()
|
|
dataStore.clubs.delete(instance: club)
|
|
dismiss()
|
|
}
|
|
}
|
|
|
|
//#Preview {
|
|
// ClubDetailView(club: Club.mock(), displayContext: .edition)
|
|
//}
|
|
|