Account creation

multistore
Laurent 2 years ago
parent 55b69bc9b4
commit f82d82663c
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 20
      PadelClub/Data/User.swift
  3. 23
      PadelClub/Extensions/Locale+Extensions.swift
  4. 2
      PadelClub/Views/User/AccountView.swift
  5. 52
      PadelClub/Views/User/LoginView.swift
  6. 79
      PadelClub/Views/User/UserCreationView.swift

@ -14,6 +14,7 @@
C425D4122B6D249E002A7B48 /* PadelClubTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C425D4112B6D249E002A7B48 /* PadelClubTests.swift */; };
C425D41C2B6D249E002A7B48 /* PadelClubUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C425D41B2B6D249E002A7B48 /* PadelClubUITests.swift */; };
C425D41E2B6D249E002A7B48 /* PadelClubUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C425D41D2B6D249E002A7B48 /* PadelClubUITestsLaunchTests.swift */; };
C44B79112BBDA63A00906534 /* Locale+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44B79102BBDA63A00906534 /* Locale+Extensions.swift */; };
C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D592B6D383C00ADC637 /* Tournament.swift */; };
C4A47D5E2B6D38EC00ADC637 /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */; };
C4A47D632B6D3D6500ADC637 /* Club.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D622B6D3D6500ADC637 /* Club.swift */; };
@ -246,6 +247,7 @@
C425D41B2B6D249E002A7B48 /* PadelClubUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadelClubUITests.swift; sourceTree = "<group>"; };
C425D41D2B6D249E002A7B48 /* PadelClubUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadelClubUITestsLaunchTests.swift; sourceTree = "<group>"; };
C425D44E2B6D24E1002A7B48 /* LeStorage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LeStorage.xcodeproj; path = ../../LeStorage/LeStorage.xcodeproj; sourceTree = "<group>"; };
C44B79102BBDA63A00906534 /* Locale+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Locale+Extensions.swift"; sourceTree = "<group>"; };
C4A47D592B6D383C00ADC637 /* Tournament.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tournament.swift; sourceTree = "<group>"; };
C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStore.swift; sourceTree = "<group>"; };
C4A47D622B6D3D6500ADC637 /* Club.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Club.swift; sourceTree = "<group>"; };
@ -946,6 +948,7 @@
FF6EC90A2B947AC000EA7F5A /* Array+Extensions.swift */,
FF5D0D732BB41DF8005CB568 /* Color+Extensions.swift */,
FFDB1C722BB2CFE900F1E467 /* MySortDescriptor.swift */,
C44B79102BBDA63A00906534 /* Locale+Extensions.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -1187,6 +1190,7 @@
FF967CF62BAED51600A9A3BD /* TournamentRunningView.swift in Sources */,
FF8F264D2BAE0B4100650388 /* TournamentDatePickerView.swift in Sources */,
FF967D042BAEF1C300A9A3BD /* MatchRowView.swift in Sources */,
C44B79112BBDA63A00906534 /* Locale+Extensions.swift in Sources */,
FF967CEA2BAEC70100A9A3BD /* GroupStage.swift in Sources */,
C4A47D742B72881F00ADC637 /* ClubView.swift in Sources */,
C4A47D902B7BBBEC00ADC637 /* StoreManager.swift in Sources */,

@ -19,14 +19,22 @@ class User: UserBase {
public var id: String = Store.randomId()
public var username: String
public var email: String?
public var email: String
var club: String?
var umpireCode: String?
var licenceId: String?
var firstName: String
var lastName: String
var phone: String?
var country: String?
init(username: String, email: String? = nil) {
init(username: String, email: String, firstName: String, lastName: String, phone: String?, country: String?) {
self.username = username
self.firstName = firstName
self.lastName = lastName
self.email = email
self.phone = phone
self.country = country
}
public func uuid() throws -> UUID {
@ -52,15 +60,19 @@ class User: UserBase {
case _club = "club"
case _umpireCode = "umpireCode"
case _licenceId = "licenceId"
case _firstName = "firstName"
case _lastName = "lastName"
case _phone = "phone"
case _country = "country"
}
}
class UserCreationForm: User, UserPasswordBase {
init(username: String, password: String, email: String?) {
init(username: String, password: String, firstName: String, lastName: String, email: String, phone: String?, country: String?) {
self.password = password
super.init(username: username, email: email)
super.init(username: username, email: email, firstName: firstName, lastName: lastName, phone: phone, country: country)
}
required init(from decoder: Decoder) throws {

@ -0,0 +1,23 @@
//
// Locale+Extensions.swift
// PadelClub
//
// Created by Laurent Morvillier on 03/04/2024.
//
import Foundation
extension Locale {
static func countries() -> [String] {
var countries: [String] = []
for countryCode in Locale.isoRegionCodes {
if let countryName = Locale.current.localizedString(forRegionCode: countryCode) {
countries.append(countryName)
}
}
return countries.sorted()
}
}

@ -27,7 +27,7 @@ struct AccountView: View {
}
#Preview {
AccountView(user: User(username: "coco")) {
AccountView(user: User(username: "coco", email: ",mail", firstName: "first", lastName: "last", phone: "44444", country: "US")) {
}
}

@ -14,6 +14,8 @@ struct LoginView: View {
@State var username: String = "razmig"
@State var password: String = "StaxKikoo12"
@State var showEmailPopup: Bool = false
@State var error: Error? = nil
@ -38,16 +40,22 @@ struct LoginView: View {
}
Section {
NavigationLink("Sign up") {
UserCreationView()
}
Button(action: {
self._signUp()
}, label: {
Text("Sign up")
})
Button(action: {
self._forgottenPassword()
self.showEmailPopup = true
}, label: {
Text("Forgotten password")
})
.alert(
Text("Password reset"),
isPresented: self.$showEmailPopup
) {
EmailConfirmationView()
} message: {
Text("Please enter your email")
}
}
}
@ -71,12 +79,34 @@ struct LoginView: View {
}
}
fileprivate func _signUp() {
}
struct EmailConfirmationView: View {
@State var email: String = ""
var body: some View {
VStack {
TextField("Email", text: self.$email)
.keyboardType(.emailAddress)
Button {
self._forgottenPassword()
} label: {
Text("Send email")
}
}
}
fileprivate func _forgottenPassword() {
// Store.main.service?.forgotPassword(user: <#T##UserBase#>)
Task {
do {
try await Store.main.service?.forgotPassword(email: self.email)
} catch {
Logger.error(error)
}
}
}
}
@ -86,3 +116,7 @@ struct LoginView: View {
LoginView(handler: { _ in })
}
}
#Preview {
EmailConfirmationView()
}

@ -11,18 +11,53 @@ import LeStorage
struct UserCreationView: View {
@State var username: String = ""
@State var password: String = ""
@State var password1: String = ""
@State var password2: String = ""
@State var email: String = ""
@State var firstName: String = ""
@State var lastName: String = ""
@State var phone: String = ""
@State var showUnmatchingPasswordView = false
@State var selectedCountryIndex = 0
let countries: [String] = Locale.countries()
var body: some View {
Form {
Section {
TextField("Username", text: self.$username)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
TextField("Email", text: self.$email)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)
}
Section {
SecureField("Password", text: self.$password1)
SecureField("Confirm password", text: self.$password2)
}
TextField("Username", text: self.$username)
.autocorrectionDisabled()
TextField("Password", text: self.$password)
.autocorrectionDisabled()
TextField("Email", text: self.$email)
Section {
TextField("First Name", text: self.$firstName)
.autocorrectionDisabled()
TextField("Last Name", text: self.$lastName)
.autocorrectionDisabled()
TextField("Phone", text: self.$phone)
.autocorrectionDisabled()
Picker("Select a country", selection: $selectedCountryIndex) {
ForEach(0..<self.countries.count, id: \.self) { index in
Text(self.countries[index]).tag(index)
}
}
.pickerStyle(DefaultPickerStyle())
.padding()
}
Section {
Button(action: {
@ -33,10 +68,30 @@ struct UserCreationView: View {
.frame(maxWidth: .infinity)
}
}
.onAppear {
self._selectCountry()
}
.alert("Password do not match", isPresented: self.$showUnmatchingPasswordView, actions: {
Button("Ok", action: {})
} )
.navigationTitle("Create user")
}
fileprivate func _selectCountry() {
guard let regionCode = Locale.current.region?.identifier, let country = Locale.current.localizedString(forRegionCode: regionCode) else {
return
}
self.selectedCountryIndex = self.countries.firstIndex(of: country) ?? 0
}
fileprivate func _create() {
guard self.password1 == self.password2 else {
self.showUnmatchingPasswordView = true
return
}
guard let service = Store.main.service else {
return
}
@ -44,10 +99,17 @@ struct UserCreationView: View {
do {
let userCreationForm = UserCreationForm(
username: self.username,
password: self.password,
email: self.email)
password: self.password1,
firstName: self.firstName,
lastName: self.lastName,
email: self.email,
phone: self.phone,
country: self.countries[self.selectedCountryIndex])
let _: User = try await service.createAccount(user: userCreationForm)
// let _ = try await service.requestToken(username: self.username, password: self.password1)
} catch {
Logger.error(error)
}
@ -55,6 +117,7 @@ struct UserCreationView: View {
}
}
#Preview {

Loading…
Cancel
Save