From 3ae4fbf7ab948543ce1b33b24d3f190896818eef Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 21 Feb 2024 15:22:02 +0100 Subject: [PATCH] Adds user related views --- PadelClub.xcodeproj/project.pbxproj | 18 +++++- PadelClub/Views/User/AccountView.swift | 25 ++++++++ PadelClub/Views/User/ChangePasswordView.swift | 57 +++++++++++++++++++ PadelClub/Views/User/LoginView.swift | 22 ++++++- PadelClub/Views/User/MainUserView.swift | 28 +++++++++ PadelClub/Views/User/User.swift | 52 +++++++++++++++++ PadelClub/Views/User/UserCreationView.swift | 4 +- 7 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 PadelClub/Views/User/AccountView.swift create mode 100644 PadelClub/Views/User/ChangePasswordView.swift create mode 100644 PadelClub/Views/User/MainUserView.swift create mode 100644 PadelClub/Views/User/User.swift diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index ab96e2a..3076d2a 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -28,6 +28,10 @@ C4A47D922B7BBBEC00ADC637 /* StoreItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D8F2B7BBBEC00ADC637 /* StoreItem.swift */; }; C4A47D9F2B7D0BCE00ADC637 /* StepperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D9E2B7D0BCE00ADC637 /* StepperView.swift */; }; C4A47DA62B83948E00ADC637 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DA52B83948E00ADC637 /* LoginView.swift */; }; + C4A47DA92B85F82100ADC637 /* ChangePasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DA82B85F82100ADC637 /* ChangePasswordView.swift */; }; + C4A47DAD2B85FCCD00ADC637 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DAC2B85FCCD00ADC637 /* User.swift */; }; + C4A47DB12B86375E00ADC637 /* MainUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DB02B86375E00ADC637 /* MainUserView.swift */; }; + C4A47DB32B86387500ADC637 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47DB22B86387500ADC637 /* AccountView.swift */; }; FF2BE4872B85E27400592328 /* LeStorage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C425D4542B6D24E2002A7B48 /* LeStorage.framework */; }; FF2BE4882B85E27400592328 /* LeStorage.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C425D4542B6D24E2002A7B48 /* LeStorage.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ @@ -103,6 +107,10 @@ C4A47D8F2B7BBBEC00ADC637 /* StoreItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreItem.swift; sourceTree = ""; }; C4A47D9E2B7D0BCE00ADC637 /* StepperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepperView.swift; sourceTree = ""; }; C4A47DA52B83948E00ADC637 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + C4A47DA82B85F82100ADC637 /* ChangePasswordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangePasswordView.swift; sourceTree = ""; }; + C4A47DAC2B85FCCD00ADC637 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + C4A47DB02B86375E00ADC637 /* MainUserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainUserView.swift; sourceTree = ""; }; + C4A47DB22B86387500ADC637 /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -242,8 +250,12 @@ C4A47D852B7BA33F00ADC637 /* User */ = { isa = PBXGroup; children = ( - C4A47D862B7BA36D00ADC637 /* UserCreationView.swift */, + C4A47DB22B86387500ADC637 /* AccountView.swift */, + C4A47DA82B85F82100ADC637 /* ChangePasswordView.swift */, C4A47DA52B83948E00ADC637 /* LoginView.swift */, + C4A47DB02B86375E00ADC637 /* MainUserView.swift */, + C4A47D862B7BA36D00ADC637 /* UserCreationView.swift */, + C4A47DAC2B85FCCD00ADC637 /* User.swift */, ); path = User; sourceTree = ""; @@ -424,6 +436,9 @@ C4A47D872B7BA36D00ADC637 /* UserCreationView.swift in Sources */, C4A47D9F2B7D0BCE00ADC637 /* StepperView.swift in Sources */, C4A47D8A2B7BBB6500ADC637 /* SubscriptionView.swift in Sources */, + C4A47DB12B86375E00ADC637 /* MainUserView.swift in Sources */, + C4A47DB32B86387500ADC637 /* AccountView.swift in Sources */, + C4A47DA92B85F82100ADC637 /* ChangePasswordView.swift in Sources */, C4A47D742B72881F00ADC637 /* ClubView.swift in Sources */, C4A47D902B7BBBEC00ADC637 /* StoreManager.swift in Sources */, C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */, @@ -434,6 +449,7 @@ C425D4032B6D249D002A7B48 /* ContentView.swift in Sources */, C425D4012B6D249D002A7B48 /* PadelClubApp.swift in Sources */, C4A47D772B73789100ADC637 /* TournamentV1.swift in Sources */, + C4A47DAD2B85FCCD00ADC637 /* User.swift in Sources */, C4A47D922B7BBBEC00ADC637 /* StoreItem.swift in Sources */, C4A47DA62B83948E00ADC637 /* LoginView.swift in Sources */, C4A47D912B7BBBEC00ADC637 /* Guard.swift in Sources */, diff --git a/PadelClub/Views/User/AccountView.swift b/PadelClub/Views/User/AccountView.swift new file mode 100644 index 0000000..e3377c9 --- /dev/null +++ b/PadelClub/Views/User/AccountView.swift @@ -0,0 +1,25 @@ +// +// AccountView.swift +// PadelClub +// +// Created by Laurent Morvillier on 21/02/2024. +// + +import SwiftUI + +struct AccountView: View { + + var user: User + + var body: some View { + Form { + NavigationLink("Change password") { + ChangePasswordView() + } + }.navigationTitle(user.username) + } +} + +#Preview { + AccountView(user: User(username: "coco")) +} diff --git a/PadelClub/Views/User/ChangePasswordView.swift b/PadelClub/Views/User/ChangePasswordView.swift new file mode 100644 index 0000000..7b56e9d --- /dev/null +++ b/PadelClub/Views/User/ChangePasswordView.swift @@ -0,0 +1,57 @@ +// +// ChangePasswordView.swift +// PadelClub +// +// Created by Laurent Morvillier on 21/02/2024. +// + +import SwiftUI +import LeStorage + +struct ChangePasswordView: View { + + @State var password1: String = "staxkikoo" + @State var password2: String = "staxkikoo" + + var body: some View { + + Form { + + SecureField("Password", text: self.$password1) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + SecureField("Password again", text: self.$password2) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + + Section { + Button(action: { + self._changePassword() + }, label: { + Text("Change password") + }) + .frame(maxWidth: .infinity) + } + } + .navigationTitle("Change password") + } + + fileprivate func _changePassword() { + guard let service = Store.main.service else { + return + } + Task { + do { + _ = try await service.changePassword(password1: self.password1, password2: self.password2) + } catch { + Logger.error(error) + } + } + + } + +} + +#Preview { + ChangePasswordView() +} diff --git a/PadelClub/Views/User/LoginView.swift b/PadelClub/Views/User/LoginView.swift index c550c25..9193e1e 100644 --- a/PadelClub/Views/User/LoginView.swift +++ b/PadelClub/Views/User/LoginView.swift @@ -32,6 +32,26 @@ struct LoginView: View { }) .frame(maxWidth: .infinity) } + + Section { + HStack { + Button(action: { + self._login() + }, label: { + Text("Sign up") + }) + .frame(maxWidth: .infinity) + Button(action: { + self._login() + }, label: { + Text("Forgotten password") + }) + .frame(maxWidth: .infinity) + + } + } + + } .navigationTitle("Login") } @@ -42,7 +62,7 @@ struct LoginView: View { } Task { do { - _ = try await service.login( + let _: User = try await service.login( username: self.username, password: self.password) } catch { diff --git a/PadelClub/Views/User/MainUserView.swift b/PadelClub/Views/User/MainUserView.swift new file mode 100644 index 0000000..0918d38 --- /dev/null +++ b/PadelClub/Views/User/MainUserView.swift @@ -0,0 +1,28 @@ +// +// UserView.swift +// PadelClub +// +// Created by Laurent Morvillier on 21/02/2024. +// + +import SwiftUI +import LeStorage + +struct MainUserView: View { + + var body: some View { + +// if let user = , Store.main.hasToken() { +// AccountView(user: user) +// } else { +// LoginView() +// } + + Text("test") + } + +} + +#Preview { + MainUserView() +} diff --git a/PadelClub/Views/User/User.swift b/PadelClub/Views/User/User.swift new file mode 100644 index 0000000..2d879ab --- /dev/null +++ b/PadelClub/Views/User/User.swift @@ -0,0 +1,52 @@ +// +// User.swift +// PadelClub +// +// Created by Laurent Morvillier on 21/02/2024. +// + +import Foundation +import LeStorage + +class User: UserBase { + public var id: String = Store.randomId() + public var username: String + public var email: String? + + init(username: String, email: String? = nil) { + self.username = username + self.email = email + } + + public func uuid() throws -> UUID { + if let uuid = UUID(uuidString: self.id) { + return uuid + } + throw UUIDError.cantConvertString(string: self.id) + } + +} + +class UserCreationForm: User, UserPasswordBase { + + init(username: String, password: String, email: String?) { + self.password = password + super.init(username: username, email: email) + } + + required init(from decoder: Decoder) throws { + fatalError("init(from:) has not been implemented") + } + + public var password: String + + private enum CodingKeys: String, CodingKey { + case password + } + + override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.password, forKey: .password) + } +} diff --git a/PadelClub/Views/User/UserCreationView.swift b/PadelClub/Views/User/UserCreationView.swift index 5f4a396..c9029c6 100644 --- a/PadelClub/Views/User/UserCreationView.swift +++ b/PadelClub/Views/User/UserCreationView.swift @@ -42,10 +42,12 @@ struct UserCreationView: View { } Task { do { - try await service.createAccount( + let userCreationForm = UserCreationForm( username: self.username, password: self.password, email: self.email) + + let _: User = try await service.createAccount(user: userCreationForm) } catch { Logger.error(error) }