@ -11,33 +11,37 @@ import LeStorage
struct CallMessageCustomizationView : View {
@ EnvironmentObject var dataStore : DataStore
var tournament : Tournament
@ FocusState private var textEditor : Bool
enum Field {
case signature
case body
case paymentMethods
case clubName
}
@ FocusState var focusedField : CallMessageCustomizationView . Field ?
@ State private var customClubName : String = " "
@ State private var customCallMessageBody : String = " "
@ State private var customCallMessageSignature : String = " "
@ State private var summonsAvailablePaymentMethods : String = " "
init ( tournament : Tournament ) {
self . tournament = tournament
_customCallMessageBody = State ( wrappedValue : DataStore . shared . user . summonsMessageBody ? ? " " )
_customCallMessageSignature = State ( wrappedValue : DataStore . shared . user . summonsMessageSignature ? ? " " )
_customClubName = State ( wrappedValue : tournament . clubName ? ? " " )
_customCallMessageBody = State ( wrappedValue : DataStore . shared . user . summonsMessageBody ? ? ( DataStore . shared . user . summonsUseFullCustomMessage ? " " : ContactType . defaultCustomMessage ) )
_customCallMessageSignature = State ( wrappedValue : DataStore . shared . user . summonsMessageSignature ? ? DataStore . shared . user . defaultSignature ( ) )
_customClubName = State ( wrappedValue : tournament . clubName ? ? " Lieu du tournoi " )
_summonsAvailablePaymentMethods = State ( wrappedValue : DataStore . shared . user . summonsAvailablePaymentMethods ? ? ContactType . defaultAvailablePaymentMethods )
}
var clubName : String {
customClubName
}
var formatMessage : String ? {
dataStore . user . summonsDisplayFormat ? tournament . matchFormat . computedLongLabel + " . " : nil
}
var entryFeeMessage : String ? {
dataStore . user . summonsDisplayEntryFee ? tournament . entryFeeMessage : nil
}
var computedMessage : String {
[ formatMessage , entryFeeMessage , customCallMessageBody ] . compacted ( ) . map { $0 . trimmed } . joined ( separator : " \n " )
[ entryFeeMessage , customCallMessageBody ] . compacted ( ) . map { $0 . trimmed } . joined ( separator : " \n " )
}
var finalMessage : String ? {
@ -48,16 +52,12 @@ struct CallMessageCustomizationView: View {
var body : some View {
@ Bindable var user = dataStore . user
List {
Section {
ZStack {
Text ( customCallMessageBody ) . hidden ( )
. padding ( . vertical , 20 )
TextEditor ( text : $ customCallMessageBody )
. autocorrectionDisabled ( )
. focused ( $ textEditor )
}
} header : {
Text ( " Personnalisation du message de convocation " )
_renderingView ( )
_optionsView ( )
_editorView ( )
if user . summonsUseFullCustomMessage {
_paymentMethodsView ( )
}
Section {
@ -65,100 +65,54 @@ struct CallMessageCustomizationView: View {
Text ( customCallMessageSignature ) . hidden ( )
TextEditor ( text : $ customCallMessageSignature )
. autocorrectionDisabled ( )
. focused ( $ textEditor )
. focused ( $ focusedField , equals : . signature )
}
} header : {
Text ( " Signature du message " )
}
_clubNameView ( )
Section {
if user . summonsUseFullCustomMessage {
Text ( self . computedFullCustomMessage ( ) )
. contextMenu {
Button ( " Coller dans le presse-papier " ) {
UIPasteboard . general . string = self . computedFullCustomMessage ( )
}
}
}
else if let finalMessage {
Text ( finalMessage )
. contextMenu {
Button ( " Coller dans le presse-papier " ) {
UIPasteboard . general . string = finalMessage
}
}
}
} header : {
Text ( " Exemple " )
}
Section {
LabeledContent {
Toggle ( isOn : $ user . summonsUseFullCustomMessage ) {
} footer : {
HStack {
Spacer ( )
FooterButtonView ( " éditer " ) {
focusedField = . signature
}
} label : {
Text ( " contrôle complet du message " )
}
} header : {
Text ( " Personnalisation complète " )
} footer : {
Text ( " Utilisez ces balises dans votre texte : #titre, #jour, #horaire, #club, #signature " )
}
_clubNameView ( )
}
. headerProminence ( . increased )
. navigationBarTitleDisplayMode ( . inline )
. toolbarBackground ( . visible , for : . navigationBar )
. navigationTitle ( " Message de convocation " )
. toolbar {
ToolbarItem ( placement : . topBarTrailing ) {
Menu {
Picker ( selection : $ user . summonsDisplayFormat ) {
Text ( " Afficher le format " ) . tag ( true )
Text ( " Masquer le format " ) . tag ( false )
} label : {
}
Picker ( selection : $ user . summonsDisplayEntryFee ) {
Text ( " Afficher le prix d'inscription " ) . tag ( true )
Text ( " Masquer le prix d'inscription " ) . tag ( false )
} label : {
}
} label : {
LabelOptions ( )
}
}
ToolbarItemGroup ( placement : . keyboard ) {
if textEditor {
if focusedField != . clubName {
Spacer ( )
Button {
textEditor = false
focusedField = nil
user . summonsMessageBody = customCallMessageBody
user . summonsMessageSignature = customCallMessageSignature
user . summonsAvailablePaymentMethods = summonsAvailablePaymentMethods
_save ( )
} label : {
Label ( " Fermer " , systemImage : " xmark " )
Text ( " Valider " )
}
. buttonStyle ( . bordered )
}
}
}
. onChange ( of : user . summonsUseFullCustomMessage ) {
user . summonsMessageBody = nil
if user . summonsUseFullCustomMessage = = false {
user . summonsMessageBody = ContactType . defaultCustomMessage
customCallMessageBody = ContactType . defaultCustomMessage
} else {
customCallMessageBody = " "
}
_save ( )
}
. onChange ( of : customCallMessageBody ) {
user . summonsMessageBody = customCallMessageBody
_save ( )
}
. onChange ( of : customCallMessageSignature ) {
user . summonsMessageSignature = customCallMessageSignature
_save ( )
}
. onChange ( of : user . summonsDisplayEntryFee ) {
_save ( )
}
. onChange ( of : user . summonsDisplayFormat ) {
_save ( )
}
}
}
private func _save ( ) {
@ -169,6 +123,68 @@ struct CallMessageCustomizationView: View {
}
}
@ ViewBuilder
private func _editorView ( ) -> some View {
@ Bindable var user = dataStore . user
Section {
ZStack {
Text ( customCallMessageBody ) . hidden ( )
. padding ( . vertical , 20 )
TextEditor ( text : $ customCallMessageBody )
. autocorrectionDisabled ( )
. focused ( $ focusedField , equals : . body )
}
} header : {
if user . summonsUseFullCustomMessage {
Text ( " Message de convocation " )
} else {
Text ( " Information supplémentaire " )
}
} footer : {
if user . summonsUseFullCustomMessage {
LazyVStack ( alignment : . leading ) {
Text ( " Utilisez ces balises " )
FooterButtonView ( " #titre " ) {
customCallMessageBody . append ( " #titre " )
focusedField = . body
}
FooterButtonView ( " #manche " ) {
customCallMessageBody . append ( " #manche " )
focusedField = . body
}
FooterButtonView ( " #prix " ) {
customCallMessageBody . append ( " #prix " )
focusedField = . body
}
FooterButtonView ( " #jour " ) {
customCallMessageBody . append ( " #jour " )
focusedField = . body
}
FooterButtonView ( " #horaire " ) {
customCallMessageBody . append ( " #horaire " )
focusedField = . body
}
FooterButtonView ( " #club " ) {
customCallMessageBody . append ( " #club " )
focusedField = . body
}
FooterButtonView ( " #signature " ) {
customCallMessageBody . append ( " #signature " )
focusedField = . body
}
}
} else {
HStack {
Spacer ( )
FooterButtonView ( " éditer " ) {
focusedField = . body
}
}
}
}
}
@ ViewBuilder
private func _clubNameView ( ) -> some View {
if let eventClub = tournament . eventObject ( ) ? . clubObject ( ) {
@ -176,6 +192,7 @@ struct CallMessageCustomizationView: View {
Section {
TextField ( " Nom du club " , text : $ customClubName )
. autocorrectionDisabled ( )
. focused ( $ focusedField , equals : . clubName )
. onSubmit {
eventClub . name = customClubName
do {
@ -190,17 +207,79 @@ struct CallMessageCustomizationView: View {
} footer : {
if hasBeenCreated = = false {
Text ( " Édition impossible, vous n'êtes pas le créateur de ce club. " ) . foregroundStyle ( . logoRed )
} else {
HStack {
Spacer ( )
FooterButtonView ( " éditer " ) {
focusedField = . clubName
}
}
}
}
}
}
@ ViewBuilder
private func _renderingView ( ) -> some View {
@ Bindable var user = dataStore . user
Section {
if user . summonsUseFullCustomMessage {
Text ( self . computedFullCustomMessage ( ) )
}
else if let finalMessage {
Text ( finalMessage )
}
} header : {
Text ( " Rendu généré automatiquement " )
}
}
@ ViewBuilder
private func _optionsView ( ) -> some View {
@ Bindable var user = dataStore . user
Section {
Toggle ( isOn : $ user . summonsUseFullCustomMessage ) {
Text ( " Tout personnaliser " )
Text ( " Écrivez votre propre message. " )
}
if user . summonsUseFullCustomMessage = = false {
Toggle ( isOn : $ user . summonsDisplayEntryFee ) {
Text ( " Afficher le prix d'inscription " )
Text ( " et les informations sur le paiement " )
}
}
} header : {
Text ( " Options " )
}
if user . summonsDisplayEntryFee && user . summonsUseFullCustomMessage = = false {
_paymentMethodsView ( )
}
}
@ ViewBuilder
private func _paymentMethodsView ( ) -> some View {
Section {
ZStack {
Text ( summonsAvailablePaymentMethods ) . hidden ( )
. padding ( . vertical , 20 )
TextEditor ( text : $ summonsAvailablePaymentMethods )
. autocorrectionDisabled ( )
. focused ( $ focusedField , equals : . paymentMethods )
}
} header : {
Text ( " Information sur le paiement " )
} footer : {
HStack {
Spacer ( )
FooterButtonView ( " éditer " ) {
focusedField = . paymentMethods
}
}
}
}
func computedFullCustomMessage ( ) -> String {
var text = customCallMessageBody . replacingOccurrences ( of : " #titre " , with : tournament . tournamentTitle ( ) )
text = text . replacingOccurrences ( of : " #club " , with : clubName )
text = text . replacingOccurrences ( of : " #jour " , with : " \( Date ( ) . formatted ( Date . FormatStyle ( ) . weekday ( . wide ) . day ( ) . month ( . wide ) ) ) " )
text = text . replacingOccurrences ( of : " #horaire " , with : " \( Date ( ) . formatted ( Date . FormatStyle ( ) . hour ( ) . minute ( ) ) ) " )
text = text . replacingOccurrences ( of : " #signature " , with : customCallMessageSignature )
return text
return ContactType . callingCustomMessage ( source : customCallMessageBody , tournament : tournament , startDate : Date ( ) , roundLabel : RoundRule . roundName ( fromRoundIndex : 2 ) )
}
}