diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..b6c6258b Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 166face2..4146a82e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.xcodeproj/project.xcworkspace/xcuserdata/ *.xcodeproj/xcuserdata/ *.xcworkspace/xcuserdata/ +*.DS_Store DerivedData/ build/ diff --git a/MobileAcebook.xcodeproj/project.pbxproj b/MobileAcebook.xcodeproj/project.pbxproj index 5506db3b..2c72b9ce 100644 --- a/MobileAcebook.xcodeproj/project.pbxproj +++ b/MobileAcebook.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 185902772AD4449A0072BFE6 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 185902762AD4449A0072BFE6 /* SignInView.swift */; }; + 18755DB92AD44EA200EBD67D /* FeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18755DB82AD44EA200EBD67D /* FeedView.swift */; }; + 18755DBB2AD4509000EBD67D /* SignUpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18755DBA2AD4509000EBD67D /* SignUpView.swift */; }; + 322FA2F42AD6B21F00DB3C70 /* CreatePostPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322FA2F32AD6B21F00DB3C70 /* CreatePostPage.swift */; }; + 322FA2F62AD6C83700DB3C70 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322FA2F52AD6C83700DB3C70 /* Post.swift */; }; AE5D85B02AC8A221009680C6 /* MobileAcebookApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE5D85AF2AC8A221009680C6 /* MobileAcebookApp.swift */; }; AE5D85B42AC8A224009680C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AE5D85B32AC8A224009680C6 /* Assets.xcassets */; }; AE5D85B72AC8A224009680C6 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AE5D85B62AC8A224009680C6 /* Preview Assets.xcassets */; }; @@ -19,6 +24,8 @@ AE5D85E32AC9AFD2009680C6 /* MockAuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE5D85E22AC9AFD2009680C6 /* MockAuthenticationService.swift */; }; AE5D85E62AC9B077009680C6 /* AuthenticationServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE5D85E52AC9B077009680C6 /* AuthenticationServiceProtocol.swift */; }; AE5D85E82AC9B29A009680C6 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE5D85E72AC9B29A009680C6 /* User.swift */; }; + C78022B72AD5770900D8A925 /* SignupPageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78022B62AD5770900D8A925 /* SignupPageService.swift */; }; + C78022C02AD5AFBF00D8A925 /* SignupPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78022BF2AD5AFBF00D8A925 /* SignupPageView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -39,6 +46,12 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 18034D252AD55C4A00B34CC3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; + 185902762AD4449A0072BFE6 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; }; + 18755DB82AD44EA200EBD67D /* FeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedView.swift; sourceTree = "<group>"; }; + 18755DBA2AD4509000EBD67D /* SignUpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpView.swift; sourceTree = "<group>"; }; + 322FA2F32AD6B21F00DB3C70 /* CreatePostPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostPage.swift; sourceTree = "<group>"; }; + 322FA2F52AD6C83700DB3C70 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; }; AE5D85AC2AC8A221009680C6 /* MobileAcebook.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MobileAcebook.app; sourceTree = BUILT_PRODUCTS_DIR; }; AE5D85AF2AC8A221009680C6 /* MobileAcebookApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileAcebookApp.swift; sourceTree = "<group>"; }; AE5D85B32AC8A224009680C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; @@ -54,6 +67,9 @@ AE5D85E22AC9AFD2009680C6 /* MockAuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthenticationService.swift; sourceTree = "<group>"; }; AE5D85E52AC9B077009680C6 /* AuthenticationServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProtocol.swift; sourceTree = "<group>"; }; AE5D85E72AC9B29A009680C6 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; }; + C78022B62AD5770900D8A925 /* SignupPageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupPageService.swift; sourceTree = "<group>"; }; + C78022BF2AD5AFBF00D8A925 /* SignupPageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignupPageView.swift; sourceTree = "<group>"; }; + C7D8387C2AD43DC900C4BBC1 /* SignupPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupPageView.swift; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,6 +104,7 @@ AE5D85BF2AC8A224009680C6 /* MobileAcebookTests */, AE5D85C92AC8A224009680C6 /* MobileAcebookUITests */, AE5D85AD2AC8A221009680C6 /* Products */, + C78022BC2AD5AEEA00D8A925 /* Recovered References */, ); sourceTree = "<group>"; }; @@ -104,6 +121,7 @@ AE5D85AE2AC8A221009680C6 /* MobileAcebook */ = { isa = PBXGroup; children = ( + 18034D252AD55C4A00B34CC3 /* Info.plist */, AE5D85E42AC9B060009680C6 /* Protocols */, AE5D85DF2AC9AF83009680C6 /* Models */, AE5D85DD2AC9AF72009680C6 /* Services */, @@ -111,6 +129,10 @@ AE5D85B32AC8A224009680C6 /* Assets.xcassets */, AE5D85B52AC8A224009680C6 /* Preview Content */, AE5D85D92AC8A337009680C6 /* WelcomePageView.swift */, + 185902762AD4449A0072BFE6 /* SignInView.swift */, + 18755DB82AD44EA200EBD67D /* FeedView.swift */, + 18755DBA2AD4509000EBD67D /* SignUpView.swift */, + C78022BF2AD5AFBF00D8A925 /* SignupPageView.swift */, ); path = MobileAcebook; sourceTree = "<group>"; @@ -146,6 +168,8 @@ isa = PBXGroup; children = ( AE5D85E02AC9AFA9009680C6 /* AuthenticationService.swift */, + C78022B62AD5770900D8A925 /* SignupPageService.swift */, + 322FA2F32AD6B21F00DB3C70 /* CreatePostPage.swift */, ); path = Services; sourceTree = "<group>"; @@ -162,6 +186,7 @@ isa = PBXGroup; children = ( AE5D85E72AC9B29A009680C6 /* User.swift */, + 322FA2F52AD6C83700DB3C70 /* Post.swift */, ); path = Models; sourceTree = "<group>"; @@ -174,6 +199,14 @@ path = Protocols; sourceTree = "<group>"; }; + C78022BC2AD5AEEA00D8A925 /* Recovered References */ = { + isa = PBXGroup; + children = ( + C7D8387C2AD43DC900C4BBC1 /* SignupPageView.swift */, + ); + name = "Recovered References"; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -304,10 +337,17 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 322FA2F42AD6B21F00DB3C70 /* CreatePostPage.swift in Sources */, AE5D85E12AC9AFA9009680C6 /* AuthenticationService.swift in Sources */, + C78022B72AD5770900D8A925 /* SignupPageService.swift in Sources */, + 322FA2F62AD6C83700DB3C70 /* Post.swift in Sources */, + 18755DB92AD44EA200EBD67D /* FeedView.swift in Sources */, + C78022C02AD5AFBF00D8A925 /* SignupPageView.swift in Sources */, AE5D85E62AC9B077009680C6 /* AuthenticationServiceProtocol.swift in Sources */, AE5D85B02AC8A221009680C6 /* MobileAcebookApp.swift in Sources */, + 18755DBB2AD4509000EBD67D /* SignUpView.swift in Sources */, AE5D85E82AC9B29A009680C6 /* User.swift in Sources */, + 185902772AD4449A0072BFE6 /* SignInView.swift in Sources */, AE5D85DA2AC8A337009680C6 /* WelcomePageView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -471,6 +511,7 @@ DEVELOPMENT_ASSET_PATHS = "\"MobileAcebook/Preview Content\""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = MobileAcebook/Info.plist; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; @@ -499,6 +540,7 @@ DEVELOPMENT_ASSET_PATHS = "\"MobileAcebook/Preview Content\""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = MobileAcebook/Info.plist; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; diff --git a/MobileAcebook.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/MobileAcebook.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/MobileAcebook.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict/> +</plist> diff --git a/MobileAcebook.xcodeproj/xcshareddata/xcschemes/MobileAcebook.xcscheme b/MobileAcebook.xcodeproj/xcshareddata/xcschemes/MobileAcebook.xcscheme new file mode 100644 index 00000000..f4918d6f --- /dev/null +++ b/MobileAcebook.xcodeproj/xcshareddata/xcschemes/MobileAcebook.xcscheme @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1500" + version = "1.7"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "AE5D85AB2AC8A221009680C6" + BuildableName = "MobileAcebook.app" + BlueprintName = "MobileAcebook" + ReferencedContainer = "container:MobileAcebook.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES" + shouldAutocreateTestPlan = "YES"> + <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "AE5D85BB2AC8A224009680C6" + BuildableName = "MobileAcebookTests.xctest" + BlueprintName = "MobileAcebookTests" + ReferencedContainer = "container:MobileAcebook.xcodeproj"> + </BuildableReference> + </TestableReference> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "AE5D85C52AC8A224009680C6" + BuildableName = "MobileAcebookUITests.xctest" + BlueprintName = "MobileAcebookUITests" + ReferencedContainer = "container:MobileAcebook.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "AE5D85AB2AC8A221009680C6" + BuildableName = "MobileAcebook.app" + BlueprintName = "MobileAcebook" + ReferencedContainer = "container:MobileAcebook.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + <CommandLineArguments> + <CommandLineArgument + argument = "-_UIConstraintBasedLayoutLogUnsatisfiable NO" + isEnabled = "YES"> + </CommandLineArgument> + </CommandLineArguments> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "AE5D85AB2AC8A221009680C6" + BuildableName = "MobileAcebook.app" + BlueprintName = "MobileAcebook" + ReferencedContainer = "container:MobileAcebook.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/MobileAcebook/FeedView.swift b/MobileAcebook/FeedView.swift new file mode 100644 index 00000000..2560522b --- /dev/null +++ b/MobileAcebook/FeedView.swift @@ -0,0 +1,41 @@ +// +// SwiftUIView.swift +// MobileAcebook +// +// Created by Alina Ermakova on 09/10/2023. +// + +import SwiftUI + +struct FeedView: View { + + @State var postTextField: String = "" + @State var postArray: [String] = [] + + var body: some View { + TextField("Write a post", text: $postTextField) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay(RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1)) + Button(action: { + createPost() + }, label: { + Text("Post") + }) + } + + func createPost() { + postArray.append(postTextField) + } +} + +struct FeedView_Previews: PreviewProvider { + static var previews: some View { + FeedView() + } +} diff --git a/MobileAcebook/Info.plist b/MobileAcebook/Info.plist new file mode 100644 index 00000000..6a6654d9 --- /dev/null +++ b/MobileAcebook/Info.plist @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSAllowsArbitraryLoads</key> + <true/> + </dict> +</dict> +</plist> diff --git a/MobileAcebook/MobileAcebookApp.swift b/MobileAcebook/MobileAcebookApp.swift index e0c3eb42..9ec8bf87 100644 --- a/MobileAcebook/MobileAcebookApp.swift +++ b/MobileAcebook/MobileAcebookApp.swift @@ -10,8 +10,10 @@ import SwiftUI @main struct MobileAcebookApp: App { var body: some Scene { - WindowGroup { - WelcomePageView() + WindowGroup { + NavigationView { + WelcomePageView() + } } } } diff --git a/MobileAcebook/Models/Post.swift b/MobileAcebook/Models/Post.swift new file mode 100644 index 00000000..ba63596c --- /dev/null +++ b/MobileAcebook/Models/Post.swift @@ -0,0 +1,15 @@ +// +// Post.swift +// MobileAcebook +// +// Created by Makers Admin on 11/10/2023. +// + + + +import Foundation + +public struct Post: Codable { + let message: String + let image: String +} diff --git a/MobileAcebook/Models/User.swift b/MobileAcebook/Models/User.swift index ea748dd0..5ccb93c7 100644 --- a/MobileAcebook/Models/User.swift +++ b/MobileAcebook/Models/User.swift @@ -4,8 +4,11 @@ // // Created by Josué Estévez Fernández on 01/10/2023. // +import Foundation -public struct User { +public struct User: Codable { + let email: String let username: String let password: String + let avatar: String? } diff --git a/MobileAcebook/Protocols/AuthenticationServiceProtocol.swift b/MobileAcebook/Protocols/AuthenticationServiceProtocol.swift index ae012f49..cc8ef8c9 100644 --- a/MobileAcebook/Protocols/AuthenticationServiceProtocol.swift +++ b/MobileAcebook/Protocols/AuthenticationServiceProtocol.swift @@ -6,5 +6,9 @@ // public protocol AuthenticationServiceProtocol { + + typealias AuthCallback = (String?, Error?) -> Void + func signUp(user: User) -> Bool + func signIn(email: String, password: String, completion: @escaping AuthCallback) } diff --git a/MobileAcebook/Services/AuthenticationService.swift b/MobileAcebook/Services/AuthenticationService.swift index 9f7181c3..8d18de71 100644 --- a/MobileAcebook/Services/AuthenticationService.swift +++ b/MobileAcebook/Services/AuthenticationService.swift @@ -4,10 +4,68 @@ // // Created by Josué Estévez Fernández on 01/10/2023. // +import Foundation class AuthenticationService: AuthenticationServiceProtocol { + + struct SignInResponse: Codable { + var token: String? + var message: String + } + + func signIn(email: String, password: String, completion: @escaping AuthCallback) { + + let urlString = "http://127.0.0.1:8080/tokens" + guard let url = URL(string: urlString) else { + completion(nil, NSError(domain: "Invalid URL", code: 400, userInfo: nil)) + return + } + + let parameters = ["email": email, "password": password] + var request = URLRequest(url: url) + request.httpMethod = "POST" + do { + request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: []) + } catch let error { + completion(nil, error) + } + + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + print(request.debug()) + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let error = error { + completion(nil, error) + return + } + if let data = data { + let decoder = JSONDecoder() + if let token = try? decoder.decode(SignInResponse.self, from: data) { + print(token) + completion(token.token, nil) + } else { + print(error) + completion(nil, NSError(domain: "Invalid data", code: 500, userInfo: nil)) + } + } + } + + task.resume() + } + + func signUp(user: User) -> Bool { // Logic to call the backend API for signing up return true // placeholder } } + +fileprivate extension URLRequest { + func debug() { + print("\(self.httpMethod!) \(self.url!)") + print("Headers:") + print(self.allHTTPHeaderFields!) + print("Body:") + print(String(data: self.httpBody ?? Data(), encoding: .utf8)!) + } +} diff --git a/MobileAcebook/Services/CreatePostPage.swift b/MobileAcebook/Services/CreatePostPage.swift new file mode 100644 index 00000000..f95f03c6 --- /dev/null +++ b/MobileAcebook/Services/CreatePostPage.swift @@ -0,0 +1,40 @@ +// +// CreatePostPage.swift +// MobileAcebook +// +// Created by Makers Admin on 11/10/2023. +// + +import SwiftUI + +class CreatePost { + let title: String + let content: String + + init(title: String, content: String) { + self.title = title + self.content = content + } + + func CreatePost() -> Void { + var request = URLRequest(url: URL(string: "http://127.0.0.1:8080/posts")!) + + request.httpMethod = "POST" + + let postData = ["title": title, "content": content] + + guard let jsonResultData = try? JSONSerialization.data(withJSONObject: postData) else { + print("data not found") + return + } + + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = jsonResultData + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + print(response) + } + task.resume() + } +} + diff --git a/MobileAcebook/Services/SignupPageService.swift b/MobileAcebook/Services/SignupPageService.swift new file mode 100644 index 00000000..8b8cd57d --- /dev/null +++ b/MobileAcebook/Services/SignupPageService.swift @@ -0,0 +1,47 @@ +// +// SignupPageService.swift +// MobileAcebook +// +// Created by Alice Birkett on 10/10/2023. +// + +import SwiftUI + +class SignupService { + let email: String + let username: String + let password: String + let password2: String + let avatar: String? + + init(email: String, username: String, password: String, password2: String, avatar: String?) { + self.email = email + self.username = username + self.password = password + self.password2 = password2 + self.avatar = avatar + } + + func createAccount () -> Void { + var request = URLRequest(url: URL(string: "http://127.0.0.1:8080/users")!) + + request.httpMethod = "POST" + + let user = User(email: email, username: username, password: password, avatar: nil) + + guard let jsonResultData = try? JSONEncoder().encode(user) else { + print("data not found") + return + } + + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = jsonResultData + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + + print(response) + } + task.resume() + } +} + diff --git a/MobileAcebook/SignInView.swift b/MobileAcebook/SignInView.swift new file mode 100644 index 00000000..eedb3fda --- /dev/null +++ b/MobileAcebook/SignInView.swift @@ -0,0 +1,87 @@ +// +// SignUpView.swift +// MobileAcebook +// +// Created by Alina Ermakova on 09/10/2023. +// + +import SwiftUI + +struct SignInView: View { + @State private var email: String = "" + @State private var password: String = "" + @State private var token: String? = nil + private var service = AuthenticationService() + @State private var loginStatus: String = "" + + var body: some View { + VStack { + Image("makers-logo") + .resizable() + .scaledToFit() + .frame(width: 200, height: 200) + .accessibilityIdentifier("makers-logo") + Text("Welcome back!") + TextField("Email", text: $email) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay( + RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1) + ) + SecureField( + "Password", + text: $password + ) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay( + RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1) + ) + Text(loginStatus) + .foregroundColor(.red) + .padding(.top, 8) + Button("Sign in") { + service.signIn(email: email, password: password) { (receivedToken, err) in + if let token = receivedToken { + self.token = token + loginStatus = "Login successful" + } else { + // No token received, check for user existence + if let error = err { + loginStatus = error.localizedDescription + } else { + loginStatus = "Invalid email or password" + } + } + } + } + .padding() + .disabled(token != nil) + .opacity(token == nil ? 1.0 : 0.5) + + NavigationLink("", + destination: FeedView(), + isActive: Binding<Bool>( + get: { self.token != nil }, + set: { _ in } + ) + ) + .opacity(token != nil ? 1.0 : 0.0) + } + } +} +struct SignInView_Previews: PreviewProvider { + static var previews: some View { + SignInView() + } +} diff --git a/MobileAcebook/SignUpView.swift b/MobileAcebook/SignUpView.swift new file mode 100644 index 00000000..7a3811d8 --- /dev/null +++ b/MobileAcebook/SignUpView.swift @@ -0,0 +1,20 @@ +// +// SignUpView.swift +// MobileAcebook +// +// Created by Alina Ermakova on 09/10/2023. +// + +import SwiftUI + +struct SignUpView: View { + var body: some View { + Text("Hello, Sign Up!") + } +} + +struct SignUpView_Previews: PreviewProvider { + static var previews: some View { + SignUpView() + } +} diff --git a/MobileAcebook/SignupPageView.swift b/MobileAcebook/SignupPageView.swift new file mode 100644 index 00000000..48d1732c --- /dev/null +++ b/MobileAcebook/SignupPageView.swift @@ -0,0 +1,136 @@ +// +// signupPageView.swift +// MobileAcebook +// +// Created by Alice Birkett on 09/10/2023. +// + +import SwiftUI + +struct SignupPageView: View { + + @State private var username: String = "" + @State private var email: String = "" + @State private var password: String = "" + @State private var password2: String = "" + @State private var avatar: String? = nil + + func submitUser() -> Void { + let signupService = SignupService(email: email, username: username, password: password, password2: password2, avatar: avatar) + signupService.createAccount() + } + + var body: some View { + VStack{ + Image("makers-logo") + .resizable() + .scaledToFit() + .frame(width: 200, height: 200) + .accessibilityIdentifier("makers-logo") + Text("Sign-up") + TextField( + "Username", + text: $username + ) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay(RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1)) + TextField( + "Email address", + text: $email) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay(RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1)) + SecureInputView( + "Password", + text: $password + ) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay(RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1)) + SecureInputView( + "Re-enter Password", + text: $password2 + ) + .padding() + .foregroundColor(.black) + .frame(width: 303, height: 36) + .background(.white) + .cornerRadius(6) + .overlay(RoundedRectangle(cornerRadius: 6) + .inset(by: 0.5) + .stroke(Color(red: 0.16, green: 0.16, blue: 0.16).opacity(0.5), lineWidth: 1)) + if password != password2 { + Text("Passwords must match!").foregroundStyle(.red) + } else if password.count < 8 { + Text("Passwords must have a length of 8 or more").foregroundStyle(.red) + } else if password.lowercased() == password { + Text("Passwords must hava a capital letter").foregroundStyle(.red) + } else { + NavigationLink(destination: SignInView()) { + Text("Submit") + + }.simultaneousGesture(TapGesture().onEnded { + submitUser() + }) + + + } + + + + } + } +} + +struct SignupPageView_Previews: PreviewProvider { + static var previews: some View { + SignupPageView() + } +} + +struct SecureInputView: View { + + @Binding private var text: String + @State private var isSecured: Bool = true + private var title: String + + init(_ title: String, text: Binding<String>) { + self.title = title + self._text = text + } + + var body: some View { + ZStack(alignment: .trailing) { + Group { + if isSecured { + SecureField(title, text: $text) + } else { + TextField(title, text: $text) + } + }.padding(.trailing, 32) + + Button(action: { + isSecured.toggle() + }) { + Image(systemName: self.isSecured ? "eye.slash" : "eye") + .accentColor(.gray) + } + } + } +} diff --git a/MobileAcebook/ViewModels/SignInViewModel.swift b/MobileAcebook/ViewModels/SignInViewModel.swift new file mode 100644 index 00000000..52c3112a --- /dev/null +++ b/MobileAcebook/ViewModels/SignInViewModel.swift @@ -0,0 +1,15 @@ +// +// SignInViewModel.swift +// MobileAcebook +// +// Created by Alina Ermakova on 10/10/2023. +// + +import Foundation + +class SignInViewModel { + + init(){ + + } +} diff --git a/MobileAcebook/WelcomePageView.swift b/MobileAcebook/WelcomePageView.swift index 96006af9..9d028c5a 100644 --- a/MobileAcebook/WelcomePageView.swift +++ b/MobileAcebook/WelcomePageView.swift @@ -7,19 +7,20 @@ import SwiftUI + struct WelcomePageView: View { var body: some View { ZStack { VStack { Spacer() - + Text("Welcome to Acebook!") .font(.largeTitle) .padding(.bottom, 20) .accessibilityIdentifier("welcomeText") - + Spacer() - + Image("makers-logo") .resizable() .scaledToFit() @@ -27,11 +28,38 @@ struct WelcomePageView: View { .accessibilityIdentifier("makers-logo") Spacer() - - Button("Sign Up") { - // TODO: sign up logic + + HStack{ + Button(action: { + print("Floating Button Click") + }, label: { + NavigationLink(destination: SignInView()) { + Text("Sign In") + .padding(.horizontal, 15) + .padding(.vertical, 12) + .background(Color.black) + .foregroundColor(.white) + .cornerRadius(10) + .font(.body) + .frame(width: 120, height: 80) + } + }) + + Button(action: { + print("Floating Button Click") + }, label: { + NavigationLink(destination: SignupPageView()) { + Text("Sign Up") + .padding(.horizontal, 12) + .padding(.vertical, 12) + .background(Color.black) + .foregroundColor(.white) + .cornerRadius(10) + .font(.body) + .frame(width: 120, height: 80) + } + }) } - .accessibilityIdentifier("signUpButton") Spacer() }