diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..7bdd859 --- /dev/null +++ b/Podfile @@ -0,0 +1,16 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'TracMobility' do + + # Pods for TracMobility + use_frameworks! + + # Authentication + pod 'Auth0', '~> 1.0' + + # Map & Location + pod 'GoogleMaps' + pod 'GooglePlaces' + +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..5910ba2 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,37 @@ +PODS: + - Auth0 (1.31.0): + - JWTDecode + - SimpleKeychain + - GoogleMaps (4.1.0): + - GoogleMaps/Maps (= 4.1.0) + - GoogleMaps/Base (4.1.0) + - GoogleMaps/Maps (4.1.0): + - GoogleMaps/Base + - GooglePlaces (4.1.0): + - GoogleMaps/Base (= 4.1.0) + - JWTDecode (2.6.0) + - SimpleKeychain (0.12.2) + +DEPENDENCIES: + - Auth0 (~> 1.0) + - GoogleMaps + - GooglePlaces + +SPEC REPOS: + trunk: + - Auth0 + - GoogleMaps + - GooglePlaces + - JWTDecode + - SimpleKeychain + +SPEC CHECKSUMS: + Auth0: 5a4ddc55570c8dfb1521de559d7f5409fd7be632 + GoogleMaps: 008e2c80e38605b56b560e8deb73d4194ff30bef + GooglePlaces: a058b776259c13e1323c9ff135549cb1b13ad8e7 + JWTDecode: 480ca441ddbd5fbfb2abf17870af62f86436be58 + SimpleKeychain: d6a74781e20ebac8cd89deebf593587913aeed07 + +PODFILE CHECKSUM: 231efc98e90adb14a5ce9763834a339f7e09d3ca + +COCOAPODS: 1.10.1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..8261138 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# iOS-Assignment +TracMobility iOS Assignment + +## Launch Screen +![Launch Screen](screenshots/IMG_3365.PNG) + +## Launch Screen Animation +![Launch Screen Animation](screenshots/RPReplay_Final1613921491.mov) + +## Sign Up (Initial) +![Sign Up Initial](screenshots/IMG_3354.PNG) + +## Sign Up (Filled) +![Sign Up Filled](screenshots/IMG_3355.PNG) + +## Sign Up (Mobile Country Code Picker) +![Sign Up Picker](screenshots/IMG_3362.PNG) + +## Sign Up (Error) +![Sign Up Error](screenshots/IMG_3364.PNG) + +## Sign Up (Auth0 Integration) +![Sign Up Autho](screenshots/IMG_3356.PNG) + +## Landing Page (Dashboard) +![Landing Page Dashboard](screenshots/IMG_3353.PNG) + +## Landing Page (Side Menu) +![Landing Page Side Menu](screenshots/IMG_3358.PNG) + +## Logout +![Logout](screenshots/IMG_3359.PNG) + +## Inbox (yet to implement) +![Pending Feature](screenshots/IMG_3360.PNG) diff --git a/TracMobility.xcodeproj/project.pbxproj b/TracMobility.xcodeproj/project.pbxproj new file mode 100644 index 0000000..dc11a77 --- /dev/null +++ b/TracMobility.xcodeproj/project.pbxproj @@ -0,0 +1,506 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 030F9D4725E12D47004C00E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D4625E12D47004C00E0 /* AppDelegate.swift */; }; + 030F9D4B25E12D47004C00E0 /* SignUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D4A25E12D47004C00E0 /* SignUpViewController.swift */; }; + 030F9D4E25E12D47004C00E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 030F9D4C25E12D47004C00E0 /* Main.storyboard */; }; + 030F9D5025E12D48004C00E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 030F9D4F25E12D48004C00E0 /* Assets.xcassets */; }; + 030F9D5325E12D48004C00E0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 030F9D5125E12D48004C00E0 /* LaunchScreen.storyboard */; }; + 030F9D6625E1395D004C00E0 /* LaunchScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D6525E1395D004C00E0 /* LaunchScreenViewController.swift */; }; + 030F9D7325E13DE6004C00E0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D7225E13DE6004C00E0 /* SceneDelegate.swift */; }; + 030F9D7D25E14B8E004C00E0 /* Countries.json in Resources */ = {isa = PBXBuildFile; fileRef = 030F9D7C25E14B8E004C00E0 /* Countries.json */; }; + 030F9D8825E14E8E004C00E0 /* Extensions&Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D8725E14E8E004C00E0 /* Extensions&Models.swift */; }; + 030F9D9325E162A4004C00E0 /* CustomUIPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9D9225E162A4004C00E0 /* CustomUIPicker.swift */; }; + 030F9D9625E162AF004C00E0 /* CustomUIPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030F9D9525E162AF004C00E0 /* CustomUIPicker.xib */; }; + 030F9DA225E17ABA004C00E0 /* DashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9DA125E17ABA004C00E0 /* DashboardViewController.swift */; }; + 030F9DA525E19719004C00E0 /* SideInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9DA425E19719004C00E0 /* SideInViewController.swift */; }; + 030F9DB725E1D898004C00E0 /* CustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9DB625E1D898004C00E0 /* CustomAlertView.swift */; }; + 030F9DBE25E201CF004C00E0 /* Authentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F9DBD25E201CF004C00E0 /* Authentication.swift */; }; + 030F9DD125E22052004C00E0 /* Auth0.plist in Resources */ = {isa = PBXBuildFile; fileRef = 030F9DD025E22052004C00E0 /* Auth0.plist */; }; + 89497C9D587CB483B8FE2D86 /* Pods_TracMobility.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A77D26EE91760906D4342CB0 /* Pods_TracMobility.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 030F9D4325E12D47004C00E0 /* TracMobility.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TracMobility.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 030F9D4625E12D47004C00E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 030F9D4A25E12D47004C00E0 /* SignUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpViewController.swift; sourceTree = ""; }; + 030F9D4D25E12D47004C00E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 030F9D4F25E12D48004C00E0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 030F9D5225E12D48004C00E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 030F9D5425E12D48004C00E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 030F9D6525E1395D004C00E0 /* LaunchScreenViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchScreenViewController.swift; sourceTree = ""; }; + 030F9D7225E13DE6004C00E0 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 030F9D7C25E14B8E004C00E0 /* Countries.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Countries.json; sourceTree = ""; }; + 030F9D8725E14E8E004C00E0 /* Extensions&Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions&Models.swift"; sourceTree = ""; }; + 030F9D9225E162A4004C00E0 /* CustomUIPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomUIPicker.swift; sourceTree = ""; }; + 030F9D9525E162AF004C00E0 /* CustomUIPicker.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomUIPicker.xib; sourceTree = ""; }; + 030F9DA125E17ABA004C00E0 /* DashboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewController.swift; sourceTree = ""; }; + 030F9DA425E19719004C00E0 /* SideInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideInViewController.swift; sourceTree = ""; }; + 030F9DB625E1D898004C00E0 /* CustomAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertView.swift; sourceTree = ""; }; + 030F9DBD25E201CF004C00E0 /* Authentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Authentication.swift; sourceTree = ""; }; + 030F9DD025E22052004C00E0 /* Auth0.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Auth0.plist; sourceTree = ""; }; + 9492F148A6F36E6269E73EEC /* Pods-TracMobility.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TracMobility.debug.xcconfig"; path = "Target Support Files/Pods-TracMobility/Pods-TracMobility.debug.xcconfig"; sourceTree = ""; }; + A5F65FB766A9A477BA836A24 /* Pods-TracMobility.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TracMobility.release.xcconfig"; path = "Target Support Files/Pods-TracMobility/Pods-TracMobility.release.xcconfig"; sourceTree = ""; }; + A77D26EE91760906D4342CB0 /* Pods_TracMobility.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TracMobility.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 030F9D4025E12D47004C00E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 89497C9D587CB483B8FE2D86 /* Pods_TracMobility.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 030F9D3A25E12D47004C00E0 = { + isa = PBXGroup; + children = ( + 030F9D4525E12D47004C00E0 /* TracMobility */, + 030F9D4425E12D47004C00E0 /* Products */, + 955E02496798D9AD72CBE2D5 /* Pods */, + 6996F450E5172F2887B0335B /* Frameworks */, + ); + sourceTree = ""; + }; + 030F9D4425E12D47004C00E0 /* Products */ = { + isa = PBXGroup; + children = ( + 030F9D4325E12D47004C00E0 /* TracMobility.app */, + ); + name = Products; + sourceTree = ""; + }; + 030F9D4525E12D47004C00E0 /* TracMobility */ = { + isa = PBXGroup; + children = ( + 030F9D4625E12D47004C00E0 /* AppDelegate.swift */, + 030F9D4F25E12D48004C00E0 /* Assets.xcassets */, + 030F9D5425E12D48004C00E0 /* Info.plist */, + 030F9DD025E22052004C00E0 /* Auth0.plist */, + 030F9D6B25E13D23004C00E0 /* ViewController */, + 030F9D7825E14ACE004C00E0 /* Utilities */, + 030F9D7925E14B2C004C00E0 /* Resources */, + 030F9D7A25E14B38004C00E0 /* Storyboards */, + ); + path = TracMobility; + sourceTree = ""; + }; + 030F9D6B25E13D23004C00E0 /* ViewController */ = { + isa = PBXGroup; + children = ( + 030F9D7225E13DE6004C00E0 /* SceneDelegate.swift */, + 030F9D6525E1395D004C00E0 /* LaunchScreenViewController.swift */, + 030F9D4A25E12D47004C00E0 /* SignUpViewController.swift */, + 030F9DA125E17ABA004C00E0 /* DashboardViewController.swift */, + 030F9DA425E19719004C00E0 /* SideInViewController.swift */, + 030F9DBD25E201CF004C00E0 /* Authentication.swift */, + ); + path = ViewController; + sourceTree = ""; + }; + 030F9D7825E14ACE004C00E0 /* Utilities */ = { + isa = PBXGroup; + children = ( + 030F9D8725E14E8E004C00E0 /* Extensions&Models.swift */, + 030F9D9225E162A4004C00E0 /* CustomUIPicker.swift */, + 030F9D9525E162AF004C00E0 /* CustomUIPicker.xib */, + 030F9DB625E1D898004C00E0 /* CustomAlertView.swift */, + ); + path = Utilities; + sourceTree = ""; + }; + 030F9D7925E14B2C004C00E0 /* Resources */ = { + isa = PBXGroup; + children = ( + 030F9D7C25E14B8E004C00E0 /* Countries.json */, + ); + path = Resources; + sourceTree = ""; + }; + 030F9D7A25E14B38004C00E0 /* Storyboards */ = { + isa = PBXGroup; + children = ( + 030F9D4C25E12D47004C00E0 /* Main.storyboard */, + 030F9D5125E12D48004C00E0 /* LaunchScreen.storyboard */, + ); + path = Storyboards; + sourceTree = ""; + }; + 6996F450E5172F2887B0335B /* Frameworks */ = { + isa = PBXGroup; + children = ( + A77D26EE91760906D4342CB0 /* Pods_TracMobility.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 955E02496798D9AD72CBE2D5 /* Pods */ = { + isa = PBXGroup; + children = ( + 9492F148A6F36E6269E73EEC /* Pods-TracMobility.debug.xcconfig */, + A5F65FB766A9A477BA836A24 /* Pods-TracMobility.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 030F9D4225E12D47004C00E0 /* TracMobility */ = { + isa = PBXNativeTarget; + buildConfigurationList = 030F9D5725E12D48004C00E0 /* Build configuration list for PBXNativeTarget "TracMobility" */; + buildPhases = ( + FCE690D74E0A5220F2E99392 /* [CP] Check Pods Manifest.lock */, + 030F9D3F25E12D47004C00E0 /* Sources */, + 030F9D4025E12D47004C00E0 /* Frameworks */, + 030F9D4125E12D47004C00E0 /* Resources */, + 4037A93E1C0E3172FE62B2B2 /* [CP] Copy Pods Resources */, + E1263F7011C8154FFC031919 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TracMobility; + productName = TracMobility; + productReference = 030F9D4325E12D47004C00E0 /* TracMobility.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 030F9D3B25E12D47004C00E0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + 030F9D4225E12D47004C00E0 = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = 030F9D3E25E12D47004C00E0 /* Build configuration list for PBXProject "TracMobility" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 030F9D3A25E12D47004C00E0; + productRefGroup = 030F9D4425E12D47004C00E0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 030F9D4225E12D47004C00E0 /* TracMobility */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 030F9D4125E12D47004C00E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 030F9D9625E162AF004C00E0 /* CustomUIPicker.xib in Resources */, + 030F9DD125E22052004C00E0 /* Auth0.plist in Resources */, + 030F9D5325E12D48004C00E0 /* LaunchScreen.storyboard in Resources */, + 030F9D5025E12D48004C00E0 /* Assets.xcassets in Resources */, + 030F9D7D25E14B8E004C00E0 /* Countries.json in Resources */, + 030F9D4E25E12D47004C00E0 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4037A93E1C0E3172FE62B2B2 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E1263F7011C8154FFC031919 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TracMobility/Pods-TracMobility-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + FCE690D74E0A5220F2E99392 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TracMobility-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 030F9D3F25E12D47004C00E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 030F9DA525E19719004C00E0 /* SideInViewController.swift in Sources */, + 030F9D8825E14E8E004C00E0 /* Extensions&Models.swift in Sources */, + 030F9DA225E17ABA004C00E0 /* DashboardViewController.swift in Sources */, + 030F9DBE25E201CF004C00E0 /* Authentication.swift in Sources */, + 030F9DB725E1D898004C00E0 /* CustomAlertView.swift in Sources */, + 030F9D7325E13DE6004C00E0 /* SceneDelegate.swift in Sources */, + 030F9D4B25E12D47004C00E0 /* SignUpViewController.swift in Sources */, + 030F9D4725E12D47004C00E0 /* AppDelegate.swift in Sources */, + 030F9D9325E162A4004C00E0 /* CustomUIPicker.swift in Sources */, + 030F9D6625E1395D004C00E0 /* LaunchScreenViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 030F9D4C25E12D47004C00E0 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 030F9D4D25E12D47004C00E0 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 030F9D5125E12D48004C00E0 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 030F9D5225E12D48004C00E0 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 030F9D5525E12D48004C00E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 030F9D5625E12D48004C00E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 030F9D5825E12D48004C00E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9492F148A6F36E6269E73EEC /* Pods-TracMobility.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SV95FNM96D; + INFOPLIST_FILE = TracMobility/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.soulmate.TracMobility; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 030F9D5925E12D48004C00E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A5F65FB766A9A477BA836A24 /* Pods-TracMobility.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SV95FNM96D; + INFOPLIST_FILE = TracMobility/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.soulmate.TracMobility; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 030F9D3E25E12D47004C00E0 /* Build configuration list for PBXProject "TracMobility" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 030F9D5525E12D48004C00E0 /* Debug */, + 030F9D5625E12D48004C00E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 030F9D5725E12D48004C00E0 /* Build configuration list for PBXNativeTarget "TracMobility" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 030F9D5825E12D48004C00E0 /* Debug */, + 030F9D5925E12D48004C00E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 030F9D3B25E12D47004C00E0 /* Project object */; +} diff --git a/TracMobility.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TracMobility.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/TracMobility.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/TracMobility.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TracMobility.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/TracMobility.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/TracMobility.xcodeproj/project.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate b/TracMobility.xcodeproj/project.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..c6ddd3e Binary files /dev/null and b/TracMobility.xcodeproj/project.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/TracMobility.xcodeproj/xcuserdata/curious_shal.xcuserdatad/xcschemes/xcschememanagement.plist b/TracMobility.xcodeproj/xcuserdata/curious_shal.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8b14e15 --- /dev/null +++ b/TracMobility.xcodeproj/xcuserdata/curious_shal.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + TracMobility.xcscheme_^#shared#^_ + + orderHint + 6 + + + + diff --git a/TracMobility.xcworkspace/contents.xcworkspacedata b/TracMobility.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..007dbb8 --- /dev/null +++ b/TracMobility.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/TracMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TracMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/TracMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/TracMobility.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate b/TracMobility.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..78a1376 Binary files /dev/null and b/TracMobility.xcworkspace/xcuserdata/curious_shal.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/TracMobility/.DS_Store b/TracMobility/.DS_Store new file mode 100644 index 0000000..8101f0a Binary files /dev/null and b/TracMobility/.DS_Store differ diff --git a/TracMobility/AppDelegate.swift b/TracMobility/AppDelegate.swift new file mode 100644 index 0000000..4455490 --- /dev/null +++ b/TracMobility/AppDelegate.swift @@ -0,0 +1,49 @@ +// +// AppDelegate.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit +import GoogleMaps +import GooglePlaces +import Auth0 + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + GMSServices.provideAPIKey("AIzaSyC7yMw-f1Kc0XhhQI7VC-BQHpETC71qo2c") + GMSPlacesClient.provideAPIKey("AIzaSyC7yMw-f1Kc0XhhQI7VC-BQHpETC71qo2c") + + //clear launch screen cache + do { + try FileManager.default.removeItem(atPath: NSHomeDirectory()+"/Library/SplashBoard") + } catch { + print("Failed to delete launch screen cache: \(error)") + } + + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { + return Auth0.resumeAuth(url, options: options) + } +} + diff --git a/TracMobility/Assets.xcassets/.DS_Store b/TracMobility/Assets.xcassets/.DS_Store new file mode 100644 index 0000000..5dbda67 Binary files /dev/null and b/TracMobility/Assets.xcassets/.DS_Store differ diff --git a/TracMobility/Assets.xcassets/AccentColor.colorset/Contents.json b/TracMobility/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/TracMobility/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/1024.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..79f60b3 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/114.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000..75ccd7c Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/120-1.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/120-1.png new file mode 100644 index 0000000..e17a497 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/120-1.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/120.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..e17a497 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/152.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..5d2df97 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/167.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..8f89c08 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/180.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..b811a01 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/20.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..55f62c0 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/29-1.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/29-1.png new file mode 100644 index 0000000..8b2859f Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/29-1.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/29.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..8b2859f Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/40-1.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/40-1.png new file mode 100644 index 0000000..79ad1c1 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/40-1.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/40.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..79ad1c1 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/57.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/57.png new file mode 100644 index 0000000..3fced82 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/58-1.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/58-1.png new file mode 100644 index 0000000..a3896e0 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/58-1.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/58.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..a3896e0 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/60.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..0bda272 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/76.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..91409b3 Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/80-1.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/80-1.png new file mode 100644 index 0000000..fdaf20d Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/80-1.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/80.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..fdaf20d Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/87.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..57c478a Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/Contents.json b/TracMobility/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..caea6da --- /dev/null +++ b/TracMobility/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,134 @@ +{ + "images" : [ + { + "filename" : "40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "29-1.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "120.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "57.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" + }, + { + "filename" : "114.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" + }, + { + "filename" : "120-1.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "icon_40pt.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "40-1.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "80-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "152.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "167.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/AppIcon.appiconset/icon_40pt.png b/TracMobility/Assets.xcassets/AppIcon.appiconset/icon_40pt.png new file mode 100644 index 0000000..320738e Binary files /dev/null and b/TracMobility/Assets.xcassets/AppIcon.appiconset/icon_40pt.png differ diff --git a/TracMobility/Assets.xcassets/App_theme_color.colorset/Contents.json b/TracMobility/Assets.xcassets/App_theme_color.colorset/Contents.json new file mode 100644 index 0000000..d0c1096 --- /dev/null +++ b/TracMobility/Assets.xcassets/App_theme_color.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x99", + "green" : "0x93", + "red" : "0x00" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x99", + "green" : "0x93", + "red" : "0x00" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-1.png b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-1.png new file mode 100644 index 0000000..ca8acfe Binary files /dev/null and b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-1.png differ diff --git a/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-2.png b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-2.png new file mode 100644 index 0000000..ca8acfe Binary files /dev/null and b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo-2.png differ diff --git a/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo.png b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo.png new file mode 100644 index 0000000..ca8acfe Binary files /dev/null and b/TracMobility/Assets.xcassets/Apple_logo.imageset/AppleLogo.png differ diff --git a/TracMobility/Assets.xcassets/Apple_logo.imageset/Contents.json b/TracMobility/Assets.xcassets/Apple_logo.imageset/Contents.json new file mode 100644 index 0000000..5fa88e9 --- /dev/null +++ b/TracMobility/Assets.xcassets/Apple_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "AppleLogo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "AppleLogo-1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "AppleLogo-2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Contents.json b/TracMobility/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/TracMobility/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Facebook_logo.imageset/Contents.json b/TracMobility/Assets.xcassets/Facebook_logo.imageset/Contents.json new file mode 100644 index 0000000..a33495f --- /dev/null +++ b/TracMobility/Assets.xcassets/Facebook_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "facebookLogo-1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "facebookLogo-2.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "facebookLogo.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-1.png b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-1.png new file mode 100644 index 0000000..651e44e Binary files /dev/null and b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-1.png differ diff --git a/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-2.png b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-2.png new file mode 100644 index 0000000..651e44e Binary files /dev/null and b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo-2.png differ diff --git a/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo.png b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo.png new file mode 100644 index 0000000..651e44e Binary files /dev/null and b/TracMobility/Assets.xcassets/Facebook_logo.imageset/facebookLogo.png differ diff --git a/TracMobility/Assets.xcassets/Google_logo.imageset/Contents.json b/TracMobility/Assets.xcassets/Google_logo.imageset/Contents.json new file mode 100644 index 0000000..3d97210 --- /dev/null +++ b/TracMobility/Assets.xcassets/Google_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icons8-google-240.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icons8-google-241.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icons8-google-242.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-240.png b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-240.png new file mode 100644 index 0000000..8f8d3ca Binary files /dev/null and b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-240.png differ diff --git a/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-241.png b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-241.png new file mode 100644 index 0000000..8f8d3ca Binary files /dev/null and b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-241.png differ diff --git a/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-242.png b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-242.png new file mode 100644 index 0000000..8f8d3ca Binary files /dev/null and b/TracMobility/Assets.xcassets/Google_logo.imageset/icons8-google-242.png differ diff --git a/TracMobility/Assets.xcassets/Inbox.imageset/Contents.json b/TracMobility/Assets.xcassets/Inbox.imageset/Contents.json new file mode 100644 index 0000000..18ca5d9 --- /dev/null +++ b/TracMobility/Assets.xcassets/Inbox.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Inbox.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Inbox@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Inbox@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Inbox.imageset/Inbox.png b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox.png new file mode 100644 index 0000000..9541261 Binary files /dev/null and b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox.png differ diff --git a/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@2x.png b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@2x.png new file mode 100644 index 0000000..12a8830 Binary files /dev/null and b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@2x.png differ diff --git a/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@3x.png b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@3x.png new file mode 100644 index 0000000..b41c53f Binary files /dev/null and b/TracMobility/Assets.xcassets/Inbox.imageset/Inbox@3x.png differ diff --git a/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/Contents.json b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/Contents.json new file mode 100644 index 0000000..8d0102d --- /dev/null +++ b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "TRAC Mobility Logo (1).png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "TRAC Mobility Logo (1)@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "TRAC Mobility Logo (1)@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1).png b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1).png new file mode 100644 index 0000000..9d94659 Binary files /dev/null and b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1).png differ diff --git a/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@2x.png b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@2x.png new file mode 100644 index 0000000..013d4f7 Binary files /dev/null and b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@2x.png differ diff --git a/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@3x.png b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@3x.png new file mode 100644 index 0000000..b64841c Binary files /dev/null and b/TracMobility/Assets.xcassets/Launchscreen_logo.imageset/TRAC Mobility Logo (1)@3x.png differ diff --git a/TracMobility/Assets.xcassets/Marker.imageset/Contents.json b/TracMobility/Assets.xcassets/Marker.imageset/Contents.json new file mode 100644 index 0000000..3cc4f4f --- /dev/null +++ b/TracMobility/Assets.xcassets/Marker.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icons8-marker-50.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icons8-marker-50@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icons8-marker-50@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50.png b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50.png new file mode 100644 index 0000000..4477e88 Binary files /dev/null and b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50.png differ diff --git a/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@2x.png b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@2x.png new file mode 100644 index 0000000..87a64bd Binary files /dev/null and b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@2x.png differ diff --git a/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@3x.png b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@3x.png new file mode 100644 index 0000000..849d95f Binary files /dev/null and b/TracMobility/Assets.xcassets/Marker.imageset/icons8-marker-50@3x.png differ diff --git a/TracMobility/Assets.xcassets/Menu.imageset/Contents.json b/TracMobility/Assets.xcassets/Menu.imageset/Contents.json new file mode 100644 index 0000000..7d4231b --- /dev/null +++ b/TracMobility/Assets.xcassets/Menu.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Menu.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Menu@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Menu@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Menu.imageset/Menu.png b/TracMobility/Assets.xcassets/Menu.imageset/Menu.png new file mode 100644 index 0000000..b4dbf2c Binary files /dev/null and b/TracMobility/Assets.xcassets/Menu.imageset/Menu.png differ diff --git a/TracMobility/Assets.xcassets/Menu.imageset/Menu@2x.png b/TracMobility/Assets.xcassets/Menu.imageset/Menu@2x.png new file mode 100644 index 0000000..9f135e5 Binary files /dev/null and b/TracMobility/Assets.xcassets/Menu.imageset/Menu@2x.png differ diff --git a/TracMobility/Assets.xcassets/Menu.imageset/Menu@3x.png b/TracMobility/Assets.xcassets/Menu.imageset/Menu@3x.png new file mode 100644 index 0000000..83a4b71 Binary files /dev/null and b/TracMobility/Assets.xcassets/Menu.imageset/Menu@3x.png differ diff --git a/TracMobility/Assets.xcassets/Trac_logo.imageset/Contents.json b/TracMobility/Assets.xcassets/Trac_logo.imageset/Contents.json new file mode 100644 index 0000000..0cc1de2 --- /dev/null +++ b/TracMobility/Assets.xcassets/Trac_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Slice@3x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Slice@3x@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Slice@3x@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x.png b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x.png new file mode 100644 index 0000000..245abdb Binary files /dev/null and b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x.png differ diff --git a/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@2x.png b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@2x.png new file mode 100644 index 0000000..fa23c77 Binary files /dev/null and b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@2x.png differ diff --git a/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@3x.png b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@3x.png new file mode 100644 index 0000000..9aa997c Binary files /dev/null and b/TracMobility/Assets.xcassets/Trac_logo.imageset/Slice@3x@3x.png differ diff --git a/TracMobility/Assets.xcassets/UserProfile.imageset/Contents.json b/TracMobility/Assets.xcassets/UserProfile.imageset/Contents.json new file mode 100644 index 0000000..320ad55 --- /dev/null +++ b/TracMobility/Assets.xcassets/UserProfile.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "UserProfile.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "UserProfile@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "UserProfile@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile.png b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile.png new file mode 100644 index 0000000..39cb9a0 Binary files /dev/null and b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile.png differ diff --git a/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@2x.png b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@2x.png new file mode 100644 index 0000000..544b200 Binary files /dev/null and b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@2x.png differ diff --git a/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@3x.png b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@3x.png new file mode 100644 index 0000000..b862e83 Binary files /dev/null and b/TracMobility/Assets.xcassets/UserProfile.imageset/UserProfile@3x.png differ diff --git a/TracMobility/Auth0.plist b/TracMobility/Auth0.plist new file mode 100644 index 0000000..7e1dbec --- /dev/null +++ b/TracMobility/Auth0.plist @@ -0,0 +1,10 @@ + + + + + Domain + dev-6bdji4nn.eu.auth0.com + ClientId + DgOO77daVXb1LADh5iHcR5EPICLshP7l + + diff --git a/TracMobility/Info.plist b/TracMobility/Info.plist new file mode 100644 index 0000000..b3cb37e --- /dev/null +++ b/TracMobility/Info.plist @@ -0,0 +1,90 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleURLTypes + + + CFBundleTypeRole + None + CFBundleURLName + auth0 + CFBundleURLSchemes + + signUp + + + + CFBundleVersion + 1 + LSApplicationCategoryType + + LSApplicationQueriesSchemes + + googlechromes + comgooglemaps + + LSRequiresIPhoneOS + + NSLocationWhenInUseUsageDescription + This lets you fetch your current location. + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIUserInterfaceStyle + Light + + diff --git a/TracMobility/Resources/Countries.json b/TracMobility/Resources/Countries.json new file mode 100644 index 0000000..255c484 --- /dev/null +++ b/TracMobility/Resources/Countries.json @@ -0,0 +1,1215 @@ +{ + + "countryPick":[{ + "name": "Afghanistan", + "dial_code": "+93", + "code": "AF" + }, + { + "name": "Aland Islands", + "dial_code": "+358", + "code": "AX" + }, + { + "name": "Albania", + "dial_code": "+355", + "code": "AL" + }, + { + "name": "Algeria", + "dial_code": "+213", + "code": "DZ" + }, + { + "name": "AmericanSamoa", + "dial_code": "+1684", + "code": "AS" + }, + { + "name": "Andorra", + "dial_code": "+376", + "code": "AD" + }, + { + "name": "Angola", + "dial_code": "+244", + "code": "AO" + }, + { + "name": "Anguilla", + "dial_code": "+1264", + "code": "AI" + }, + { + "name": "Antarctica", + "dial_code": "+672", + "code": "AQ" + }, + { + "name": "Antigua and Barbuda", + "dial_code": "+1268", + "code": "AG" + }, + { + "name": "Argentina", + "dial_code": "+54", + "code": "AR" + }, + { + "name": "Armenia", + "dial_code": "+374", + "code": "AM" + }, + { + "name": "Aruba", + "dial_code": "+297", + "code": "AW" + }, + { + "name": "Australia", + "dial_code": "+61", + "code": "AU" + }, + { + "name": "Austria", + "dial_code": "+43", + "code": "AT" + }, + { + "name": "Azerbaijan", + "dial_code": "+994", + "code": "AZ" + }, + { + "name": "Bahamas", + "dial_code": "+1242", + "code": "BS" + }, + { + "name": "Bahrain", + "dial_code": "+973", + "code": "BH" + }, + { + "name": "Bangladesh", + "dial_code": "+880", + "code": "BD" + }, + { + "name": "Barbados", + "dial_code": "+1246", + "code": "BB" + }, + { + "name": "Belarus", + "dial_code": "+375", + "code": "BY" + }, + { + "name": "Belgium", + "dial_code": "+32", + "code": "BE" + }, + { + "name": "Belize", + "dial_code": "+501", + "code": "BZ" + }, + { + "name": "Benin", + "dial_code": "+229", + "code": "BJ" + }, + { + "name": "Bermuda", + "dial_code": "+1441", + "code": "BM" + }, + { + "name": "Bhutan", + "dial_code": "+975", + "code": "BT" + }, + { + "name": "Bolivia, Plurinational State of", + "dial_code": "+591", + "code": "BO" + }, + { + "name": "Bosnia and Herzegovina", + "dial_code": "+387", + "code": "BA" + }, + { + "name": "Botswana", + "dial_code": "+267", + "code": "BW" + }, + { + "name": "Brazil", + "dial_code": "+55", + "code": "BR" + }, + { + "name": "British Indian Ocean Territory", + "dial_code": "+246", + "code": "IO" + }, + { + "name": "Brunei Darussalam", + "dial_code": "+673", + "code": "BN" + }, + { + "name": "Bulgaria", + "dial_code": "+359", + "code": "BG" + }, + { + "name": "Burkina Faso", + "dial_code": "+226", + "code": "BF" + }, + { + "name": "Burundi", + "dial_code": "+257", + "code": "BI" + }, + { + "name": "Cambodia", + "dial_code": "+855", + "code": "KH" + }, + { + "name": "Cameroon", + "dial_code": "+237", + "code": "CM" + }, + { + "name": "Canada", + "dial_code": "+1", + "code": "CA" + }, + { + "name": "Cape Verde", + "dial_code": "+238", + "code": "CV" + }, + { + "name": "Cayman Islands", + "dial_code": "+ 345", + "code": "KY" + }, + { + "name": "Central African Republic", + "dial_code": "+236", + "code": "CF" + }, + { + "name": "Chad", + "dial_code": "+235", + "code": "TD" + }, + { + "name": "Chile", + "dial_code": "+56", + "code": "CL" + }, + { + "name": "China", + "dial_code": "+86", + "code": "CN" + }, + { + "name": "Christmas Island", + "dial_code": "+61", + "code": "CX" + }, + { + "name": "Cocos (Keeling) Islands", + "dial_code": "+61", + "code": "CC" + }, + { + "name": "Colombia", + "dial_code": "+57", + "code": "CO" + }, + { + "name": "Comoros", + "dial_code": "+269", + "code": "KM" + }, + { + "name": "Congo", + "dial_code": "+242", + "code": "CG" + }, + { + "name": "Congo, The Democratic Republic of the Congo", + "dial_code": "+243", + "code": "CD" + }, + { + "name": "Cook Islands", + "dial_code": "+682", + "code": "CK" + }, + { + "name": "Costa Rica", + "dial_code": "+506", + "code": "CR" + }, + { + "name": "Cote d'Ivoire", + "dial_code": "+225", + "code": "CI" + }, + { + "name": "Croatia", + "dial_code": "+385", + "code": "HR" + }, + { + "name": "Cuba", + "dial_code": "+53", + "code": "CU" + }, + { + "name": "Cyprus", + "dial_code": "+357", + "code": "CY" + }, + { + "name": "Czech Republic", + "dial_code": "+420", + "code": "CZ" + }, + { + "name": "Denmark", + "dial_code": "+45", + "code": "DK" + }, + { + "name": "Djibouti", + "dial_code": "+253", + "code": "DJ" + }, + { + "name": "Dominica", + "dial_code": "+1767", + "code": "DM" + }, + { + "name": "Dominican Republic", + "dial_code": "+1849", + "code": "DO" + }, + { + "name": "Ecuador", + "dial_code": "+593", + "code": "EC" + }, + { + "name": "Egypt", + "dial_code": "+20", + "code": "EG" + }, + { + "name": "El Salvador", + "dial_code": "+503", + "code": "SV" + }, + { + "name": "Equatorial Guinea", + "dial_code": "+240", + "code": "GQ" + }, + { + "name": "Eritrea", + "dial_code": "+291", + "code": "ER" + }, + { + "name": "Estonia", + "dial_code": "+372", + "code": "EE" + }, + { + "name": "Ethiopia", + "dial_code": "+251", + "code": "ET" + }, + { + "name": "Falkland Islands (Malvinas)", + "dial_code": "+500", + "code": "FK" + }, + { + "name": "Faroe Islands", + "dial_code": "+298", + "code": "FO" + }, + { + "name": "Fiji", + "dial_code": "+679", + "code": "FJ" + }, + { + "name": "Finland", + "dial_code": "+358", + "code": "FI" + }, + { + "name": "France", + "dial_code": "+33", + "code": "FR" + }, + { + "name": "French Guiana", + "dial_code": "+594", + "code": "GF" + }, + { + "name": "French Polynesia", + "dial_code": "+689", + "code": "PF" + }, + { + "name": "Gabon", + "dial_code": "+241", + "code": "GA" + }, + { + "name": "Gambia", + "dial_code": "+220", + "code": "GM" + }, + { + "name": "Georgia", + "dial_code": "+995", + "code": "GE" + }, + { + "name": "Germany", + "dial_code": "+49", + "code": "DE" + }, + { + "name": "Ghana", + "dial_code": "+233", + "code": "GH" + }, + { + "name": "Gibraltar", + "dial_code": "+350", + "code": "GI" + }, + { + "name": "Greece", + "dial_code": "+30", + "code": "GR" + }, + { + "name": "Greenland", + "dial_code": "+299", + "code": "GL" + }, + { + "name": "Grenada", + "dial_code": "+1473", + "code": "GD" + }, + { + "name": "Guadeloupe", + "dial_code": "+590", + "code": "GP" + }, + { + "name": "Guam", + "dial_code": "+1671", + "code": "GU" + }, + { + "name": "Guatemala", + "dial_code": "+502", + "code": "GT" + }, + { + "name": "Guernsey", + "dial_code": "+44", + "code": "GG" + }, + { + "name": "Guinea", + "dial_code": "+224", + "code": "GN" + }, + { + "name": "Guinea-Bissau", + "dial_code": "+245", + "code": "GW" + }, + { + "name": "Guyana", + "dial_code": "+595", + "code": "GY" + }, + { + "name": "Haiti", + "dial_code": "+509", + "code": "HT" + }, + { + "name": "Holy See (Vatican City State)", + "dial_code": "+379", + "code": "VA" + }, + { + "name": "Honduras", + "dial_code": "+504", + "code": "HN" + }, + { + "name": "Hong Kong", + "dial_code": "+852", + "code": "HK" + }, + { + "name": "Hungary", + "dial_code": "+36", + "code": "HU" + }, + { + "name": "Iceland", + "dial_code": "+354", + "code": "IS" + }, + { + "name": "India", + "dial_code": "+91", + "code": "IN" + }, + { + "name": "Indonesia", + "dial_code": "+62", + "code": "ID" + }, + { + "name": "Iran, Islamic Republic of Persian Gulf", + "dial_code": "+98", + "code": "IR" + }, + { + "name": "Iraq", + "dial_code": "+964", + "code": "IQ" + }, + { + "name": "Ireland", + "dial_code": "+353", + "code": "IE" + }, + { + "name": "Isle of Man", + "dial_code": "+44", + "code": "IM" + }, + { + "name": "Israel", + "dial_code": "+972", + "code": "IL" + }, + { + "name": "Italy", + "dial_code": "+39", + "code": "IT" + }, + { + "name": "Jamaica", + "dial_code": "+1876", + "code": "JM" + }, + { + "name": "Japan", + "dial_code": "+81", + "code": "JP" + }, + { + "name": "Jersey", + "dial_code": "+44", + "code": "JE" + }, + { + "name": "Jordan", + "dial_code": "+962", + "code": "JO" + }, + { + "name": "Kazakhstan", + "dial_code": "+77", + "code": "KZ" + }, + { + "name": "Kenya", + "dial_code": "+254", + "code": "KE" + }, + { + "name": "Kiribati", + "dial_code": "+686", + "code": "KI" + }, + { + "name": "Korea, Democratic People's Republic of Korea", + "dial_code": "+850", + "code": "KP" + }, + { + "name": "Korea, Republic of South Korea", + "dial_code": "+82", + "code": "KR" + }, + { + "name": "Kuwait", + "dial_code": "+965", + "code": "KW" + }, + { + "name": "Kyrgyzstan", + "dial_code": "+996", + "code": "KG" + }, + { + "name": "Laos", + "dial_code": "+856", + "code": "LA" + }, + { + "name": "Latvia", + "dial_code": "+371", + "code": "LV" + }, + { + "name": "Lebanon", + "dial_code": "+961", + "code": "LB" + }, + { + "name": "Lesotho", + "dial_code": "+266", + "code": "LS" + }, + { + "name": "Liberia", + "dial_code": "+231", + "code": "LR" + }, + { + "name": "Libyan Arab Jamahiriya", + "dial_code": "+218", + "code": "LY" + }, + { + "name": "Liechtenstein", + "dial_code": "+423", + "code": "LI" + }, + { + "name": "Lithuania", + "dial_code": "+370", + "code": "LT" + }, + { + "name": "Luxembourg", + "dial_code": "+352", + "code": "LU" + }, + { + "name": "Macao", + "dial_code": "+853", + "code": "MO" + }, + { + "name": "Macedonia", + "dial_code": "+389", + "code": "MK" + }, + { + "name": "Madagascar", + "dial_code": "+261", + "code": "MG" + }, + { + "name": "Malawi", + "dial_code": "+265", + "code": "MW" + }, + { + "name": "Malaysia", + "dial_code": "+60", + "code": "MY" + }, + { + "name": "Maldives", + "dial_code": "+960", + "code": "MV" + }, + { + "name": "Mali", + "dial_code": "+223", + "code": "ML" + }, + { + "name": "Malta", + "dial_code": "+356", + "code": "MT" + }, + { + "name": "Marshall Islands", + "dial_code": "+692", + "code": "MH" + }, + { + "name": "Martinique", + "dial_code": "+596", + "code": "MQ" + }, + { + "name": "Mauritania", + "dial_code": "+222", + "code": "MR" + }, + { + "name": "Mauritius", + "dial_code": "+230", + "code": "MU" + }, + { + "name": "Mayotte", + "dial_code": "+262", + "code": "YT" + }, + { + "name": "Mexico", + "dial_code": "+52", + "code": "MX" + }, + { + "name": "Micronesia, Federated States of Micronesia", + "dial_code": "+691", + "code": "FM" + }, + { + "name": "Moldova", + "dial_code": "+373", + "code": "MD" + }, + { + "name": "Monaco", + "dial_code": "+377", + "code": "MC" + }, + { + "name": "Mongolia", + "dial_code": "+976", + "code": "MN" + }, + { + "name": "Montenegro", + "dial_code": "+382", + "code": "ME" + }, + { + "name": "Montserrat", + "dial_code": "+1664", + "code": "MS" + }, + { + "name": "Morocco", + "dial_code": "+212", + "code": "MA" + }, + { + "name": "Mozambique", + "dial_code": "+258", + "code": "MZ" + }, + { + "name": "Myanmar", + "dial_code": "+95", + "code": "MM" + }, + { + "name": "Namibia", + "dial_code": "+264", + "code": "NA" + }, + { + "name": "Nauru", + "dial_code": "+674", + "code": "NR" + }, + { + "name": "Nepal", + "dial_code": "+977", + "code": "NP" + }, + { + "name": "Netherlands", + "dial_code": "+31", + "code": "NL" + }, + { + "name": "Netherlands Antilles", + "dial_code": "+599", + "code": "AN" + }, + { + "name": "New Caledonia", + "dial_code": "+687", + "code": "NC" + }, + { + "name": "New Zealand", + "dial_code": "+64", + "code": "NZ" + }, + { + "name": "Nicaragua", + "dial_code": "+505", + "code": "NI" + }, + { + "name": "Niger", + "dial_code": "+227", + "code": "NE" + }, + { + "name": "Nigeria", + "dial_code": "+234", + "code": "NG" + }, + { + "name": "Niue", + "dial_code": "+683", + "code": "NU" + }, + { + "name": "Norfolk Island", + "dial_code": "+672", + "code": "NF" + }, + { + "name": "Northern Mariana Islands", + "dial_code": "+1670", + "code": "MP" + }, + { + "name": "Norway", + "dial_code": "+47", + "code": "NO" + }, + { + "name": "Oman", + "dial_code": "+968", + "code": "OM" + }, + { + "name": "Pakistan", + "dial_code": "+92", + "code": "PK" + }, + { + "name": "Palau", + "dial_code": "+680", + "code": "PW" + }, + { + "name": "Palestinian Territory, Occupied", + "dial_code": "+970", + "code": "PS" + }, + { + "name": "Panama", + "dial_code": "+507", + "code": "PA" + }, + { + "name": "Papua New Guinea", + "dial_code": "+675", + "code": "PG" + }, + { + "name": "Paraguay", + "dial_code": "+595", + "code": "PY" + }, + { + "name": "Peru", + "dial_code": "+51", + "code": "PE" + }, + { + "name": "Philippines", + "dial_code": "+63", + "code": "PH" + }, + { + "name": "Pitcairn", + "dial_code": "+872", + "code": "PN" + }, + { + "name": "Poland", + "dial_code": "+48", + "code": "PL" + }, + { + "name": "Portugal", + "dial_code": "+351", + "code": "PT" + }, + { + "name": "Puerto Rico", + "dial_code": "+1939", + "code": "PR" + }, + { + "name": "Qatar", + "dial_code": "+974", + "code": "QA" + }, + { + "name": "Romania", + "dial_code": "+40", + "code": "RO" + }, + { + "name": "Russia", + "dial_code": "+7", + "code": "RU" + }, + { + "name": "Rwanda", + "dial_code": "+250", + "code": "RW" + }, + { + "name": "Reunion", + "dial_code": "+262", + "code": "RE" + }, + { + "name": "Saint Barthelemy", + "dial_code": "+590", + "code": "BL" + }, + { + "name": "Saint Helena, Ascension and Tristan Da Cunha", + "dial_code": "+290", + "code": "SH" + }, + { + "name": "Saint Kitts and Nevis", + "dial_code": "+1869", + "code": "KN" + }, + { + "name": "Saint Lucia", + "dial_code": "+1758", + "code": "LC" + }, + { + "name": "Saint Martin", + "dial_code": "+590", + "code": "MF" + }, + { + "name": "Saint Pierre and Miquelon", + "dial_code": "+508", + "code": "PM" + }, + { + "name": "Saint Vincent and the Grenadines", + "dial_code": "+1784", + "code": "VC" + }, + { + "name": "Samoa", + "dial_code": "+685", + "code": "WS" + }, + { + "name": "San Marino", + "dial_code": "+378", + "code": "SM" + }, + { + "name": "Sao Tome and Principe", + "dial_code": "+239", + "code": "ST" + }, + { + "name": "Saudi Arabia", + "dial_code": "+966", + "code": "SA" + }, + { + "name": "Senegal", + "dial_code": "+221", + "code": "SN" + }, + { + "name": "Serbia", + "dial_code": "+381", + "code": "RS" + }, + { + "name": "Seychelles", + "dial_code": "+248", + "code": "SC" + }, + { + "name": "Sierra Leone", + "dial_code": "+232", + "code": "SL" + }, + { + "name": "Singapore", + "dial_code": "+65", + "code": "SG" + }, + { + "name": "Slovakia", + "dial_code": "+421", + "code": "SK" + }, + { + "name": "Slovenia", + "dial_code": "+386", + "code": "SI" + }, + { + "name": "Solomon Islands", + "dial_code": "+677", + "code": "SB" + }, + { + "name": "Somalia", + "dial_code": "+252", + "code": "SO" + }, + { + "name": "South Africa", + "dial_code": "+27", + "code": "ZA" + }, + { + "name": "South Sudan", + "dial_code": "+211", + "code": "SS" + }, + { + "name": "South Georgia and the South Sandwich Islands", + "dial_code": "+500", + "code": "GS" + }, + { + "name": "Spain", + "dial_code": "+34", + "code": "ES" + }, + { + "name": "Sri Lanka", + "dial_code": "+94", + "code": "LK" + }, + { + "name": "Sudan", + "dial_code": "+249", + "code": "SD" + }, + { + "name": "Suriname", + "dial_code": "+597", + "code": "SR" + }, + { + "name": "Svalbard and Jan Mayen", + "dial_code": "+47", + "code": "SJ" + }, + { + "name": "Swaziland", + "dial_code": "+268", + "code": "SZ" + }, + { + "name": "Sweden", + "dial_code": "+46", + "code": "SE" + }, + { + "name": "Switzerland", + "dial_code": "+41", + "code": "CH" + }, + { + "name": "Syrian Arab Republic", + "dial_code": "+963", + "code": "SY" + }, + { + "name": "Taiwan", + "dial_code": "+886", + "code": "TW" + }, + { + "name": "Tajikistan", + "dial_code": "+992", + "code": "TJ" + }, + { + "name": "Tanzania, United Republic of Tanzania", + "dial_code": "+255", + "code": "TZ" + }, + { + "name": "Thailand", + "dial_code": "+66", + "code": "TH" + }, + { + "name": "Timor-Leste", + "dial_code": "+670", + "code": "TL" + }, + { + "name": "Togo", + "dial_code": "+228", + "code": "TG" + }, + { + "name": "Tokelau", + "dial_code": "+690", + "code": "TK" + }, + { + "name": "Tonga", + "dial_code": "+676", + "code": "TO" + }, + { + "name": "Trinidad and Tobago", + "dial_code": "+1868", + "code": "TT" + }, + { + "name": "Tunisia", + "dial_code": "+216", + "code": "TN" + }, + { + "name": "Turkey", + "dial_code": "+90", + "code": "TR" + }, + { + "name": "Turkmenistan", + "dial_code": "+993", + "code": "TM" + }, + { + "name": "Turks and Caicos Islands", + "dial_code": "+1649", + "code": "TC" + }, + { + "name": "Tuvalu", + "dial_code": "+688", + "code": "TV" + }, + { + "name": "Uganda", + "dial_code": "+256", + "code": "UG" + }, + { + "name": "Ukraine", + "dial_code": "+380", + "code": "UA" + }, + { + "name": "United Arab Emirates", + "dial_code": "+971", + "code": "AE" + }, + { + "name": "United Kingdom", + "dial_code": "+44", + "code": "GB" + }, + { + "name": "United States", + "dial_code": "+1", + "code": "US" + }, + { + "name": "Uruguay", + "dial_code": "+598", + "code": "UY" + }, + { + "name": "Uzbekistan", + "dial_code": "+998", + "code": "UZ" + }, + { + "name": "Vanuatu", + "dial_code": "+678", + "code": "VU" + }, + { + "name": "Venezuela, Bolivarian Republic of Venezuela", + "dial_code": "+58", + "code": "VE" + }, + { + "name": "Vietnam", + "dial_code": "+84", + "code": "VN" + }, + { + "name": "Virgin Islands, British", + "dial_code": "+1284", + "code": "VG" + }, + { + "name": "Virgin Islands, U.S.", + "dial_code": "+1340", + "code": "VI" + }, + { + "name": "Wallis and Futuna", + "dial_code": "+681", + "code": "WF" + }, + { + "name": "Yemen", + "dial_code": "+967", + "code": "YE" + }, + { + "name": "Zambia", + "dial_code": "+260", + "code": "ZM" + }, + { + "name": "Zimbabwe", + "dial_code": "+263", + "code": "ZW" + } + ] +} + diff --git a/TracMobility/Storyboards/Base.lproj/LaunchScreen.storyboard b/TracMobility/Storyboards/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..cd7b662 --- /dev/null +++ b/TracMobility/Storyboards/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TracMobility/Storyboards/Base.lproj/Main.storyboard b/TracMobility/Storyboards/Base.lproj/Main.storyboard new file mode 100644 index 0000000..ac40acb --- /dev/null +++ b/TracMobility/Storyboards/Base.lproj/Main.storyboard @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TracMobility/Utilities/CustomAlertView.swift b/TracMobility/Utilities/CustomAlertView.swift new file mode 100644 index 0000000..8a238a3 --- /dev/null +++ b/TracMobility/Utilities/CustomAlertView.swift @@ -0,0 +1,107 @@ +// +// CustomAlertView.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +/// `AlertView Controller` +class CustomAlertView: UIAlertController { + + static let sharedInstance = CustomAlertView() + + //default alert with ok and cancel actions + func defaultAlert(_ view: UIViewController,_ title: String?,_ message: String?,_ okText: String?,_ okStyle: UIAlertAction.Style,_ cancelText: String?,_ cancelStyle: UIAlertAction.Style, alertStyle preffered: UIAlertController.Style) { + + DispatchQueue.main.async(execute: { + let alert = UIAlertController(title: title, message: message, preferredStyle: preffered) + let okAction = UIAlertAction(title: okText ?? "OK", style: okStyle, handler: nil) + let cancelAction = UIAlertAction(title: cancelText ?? "Cancel", style: cancelStyle, handler: nil) + + alert.addAction(okAction) + alert.addAction(cancelAction) + view.present(alert, animated: true) + }) + } + + //alert with ok action + func okAlert(_ view: UIViewController,_ title: String?,_ message: String?,_ okText: String?,_ okStyle: UIAlertAction.Style, alertStyle preffered: UIAlertController.Style) { + + DispatchQueue.main.async(execute: { + let alert = UIAlertController(title: title, message: message, preferredStyle: preffered) + let okAction = UIAlertAction(title: okText ?? "OK", style: okStyle, handler: nil) + + alert.addAction(okAction) + view.present(alert, animated: true) + }) + } + + //alert with timer + func timerAlert(_ view: UIViewController,_ title: String?,_ message: String?,_ timer: DispatchTime, alertStyle preffered: UIAlertController.Style) { + + DispatchQueue.main.async(execute: { + let alert = UIAlertController(title: title, message: message, preferredStyle: preffered) + + view.present(alert, animated: true) + + DispatchQueue.main.asyncAfter(deadline: timer){ + alert.dismiss(animated: true, completion: nil) + } + }) + } +} + +/// `Activity Indicator` +class CustomActivityIndicator: UIActivityIndicatorView { + + static var sharedInstance = CustomActivityIndicator() + var activity = UIActivityIndicatorView() + + //present the activity indicator + func presentActivityIndicator(_ viewController: UIViewController) { + DispatchQueue.main.async { + self.activity = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) + self.activity.style = UIActivityIndicatorView.Style.large + + self.activity.center = viewController.view.center + viewController.view.addSubview(self.activity) + self.activity.startAnimating() + } + } + + //start animating + func startAnimating(_ viewController: UIViewController) { + DispatchQueue.main.async { + self.activity.isHidden = false + self.activity.startAnimating() + + //If the indicator is active, disable user interaction + viewController.view.isUserInteractionEnabled = false + if let leftNavigationItem = viewController.navigationItem.leftBarButtonItems { + for (index, _) in leftNavigationItem.enumerated() { + viewController.navigationItem.leftBarButtonItems?[index].isEnabled = false + } + } + } + } + + //stop animating + func stopAnimating(_ viewController: UIViewController) { + DispatchQueue.main.async { + self.activity.stopAnimating() + self.activity.isHidden = true + + //If the indicator is inactive, enable user interaction + viewController.view.isUserInteractionEnabled = true + if let leftNavigationItem = viewController.navigationItem.leftBarButtonItems { + for (index, _) in leftNavigationItem.enumerated() { + viewController.navigationItem.leftBarButtonItems?[index].isEnabled = true + } + } + + } + } +} + diff --git a/TracMobility/Utilities/CustomUIPicker.swift b/TracMobility/Utilities/CustomUIPicker.swift new file mode 100644 index 0000000..6b305a7 --- /dev/null +++ b/TracMobility/Utilities/CustomUIPicker.swift @@ -0,0 +1,218 @@ +// +// CustomUIPicker.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +protocol CustomUIPickerDelegate: class { + func customPicker(_ amPicker: CustomUIPicker, didSelect row: Int, value: String) + func customPickerDidCancelSelection(_ amPicker: CustomUIPicker) +} + +class CustomUIPicker: UIView, UIPickerViewDelegate, UIPickerViewDataSource { + + @IBOutlet weak var confirmButton: UIButton! + @IBOutlet weak var cancelButton: UIButton! + @IBOutlet weak var toolBar: UIView! + @IBOutlet weak var picker: UIPickerView! + @IBAction func cancelButtonTapped(_ sender: UIButton) { + dismiss() + delegate?.customPickerDidCancelSelection(self) + } + + @IBAction func confirmButtonTapped(_ sender: UIButton) { + dismiss() + + var defaultRow = Int() + var defaultValue = String() + + if let selectedRow = config.selectedRow { + if selectedRow < self.config.pickerArray.count { + defaultRow = selectedRow + defaultValue = self.config.pickerArray[defaultRow] + } else { + defaultRow = 0 + defaultValue = self.config.pickerArray[0] + } + } else { + defaultRow = 0 + defaultValue = self.config.pickerArray[0] + } + + delegate?.customPicker(self, didSelect: pickerRow ?? defaultRow, value: pickerValue ?? defaultValue) + } + + // MARK: - Config + struct Config { + + fileprivate let contentHeight: CGFloat = 250 + fileprivate let bouncingOffset: CGFloat = 20 + + var pickerArray = [String]() + var selectedRow:Int? + var rowHeight:Int? + var animationDuration: TimeInterval = 0.3 + var pickerTag = 0 + + var overlayBackgroundColor: UIColor = UIColor.black.withAlphaComponent(0.6) + } + + var config = Config() + weak var delegate: CustomUIPickerDelegate? + var bottomConstraint: NSLayoutConstraint! + var overlayButton = UIButton() + var pickerValue:String? + var pickerRow:Int? + + // MARK: - Init + static func getFromNib() -> CustomUIPicker { + self.superclass() + return UINib.init(nibName: String(describing: self), bundle: nil).instantiate(withOwner: self, options: nil).last as! CustomUIPicker + } + + // MARK: - Private + fileprivate func setup(_ parentVC: UIViewController) { + + // Loading configuration + picker.reloadAllComponents() + if let selectedRow = config.selectedRow { + let when = DispatchTime.now() + 0.1 + DispatchQueue.main.asyncAfter(deadline: when){ + if selectedRow < self.config.pickerArray.count { + + self.pickerRow = selectedRow + self.pickerValue = self.config.pickerArray[selectedRow] + self.picker.selectRow(selectedRow, inComponent: 0, animated: true) + } + } + } + + // Overlay view constraints setup + overlayButton = UIButton(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)) + overlayButton.backgroundColor = config.overlayBackgroundColor + overlayButton.alpha = 0 + + overlayButton.addTarget(self, action: #selector(cancelButtonTapped(_:)), for: .touchUpInside) + + if !overlayButton.isDescendant(of: parentVC.view) { parentVC.view.addSubview(overlayButton) } + + overlayButton.translatesAutoresizingMaskIntoConstraints = false + + parentVC.view.addConstraints([ + NSLayoutConstraint(item: overlayButton, attribute: .bottom, relatedBy: .equal, toItem: parentVC.view, attribute: .bottom, multiplier: 1, constant: 0), + NSLayoutConstraint(item: overlayButton, attribute: .top, relatedBy: .equal, toItem: parentVC.view, attribute: .top, multiplier: 1, constant: 0), + NSLayoutConstraint(item: overlayButton, attribute: .leading, relatedBy: .equal, toItem: parentVC.view, attribute: .leading, multiplier: 1, constant: 0), + NSLayoutConstraint(item: overlayButton, attribute: .trailing, relatedBy: .equal, toItem: parentVC.view, attribute: .trailing, multiplier: 1, constant: 0) + ] + ) + + // Setup picker constraints + + frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: config.contentHeight) + + translatesAutoresizingMaskIntoConstraints = false + + bottomConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: parentVC.view, attribute: .bottom, multiplier: 1, constant: 0) + + if !isDescendant(of: parentVC.view) { parentVC.view.addSubview(self) } + + parentVC.view.addConstraints([ + bottomConstraint, + NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: parentVC.view, attribute: .leading, multiplier: 1, constant: 0), + NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal, toItem: parentVC.view, attribute: .trailing, multiplier: 1, constant: 0) + ] + ) + addConstraint( + NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: frame.height) + ) + move(goUp: false) + } + + fileprivate func move(goUp: Bool) { + bottomConstraint.constant = goUp ? config.bouncingOffset : config.contentHeight + } + + // MARK: - Public + func show(inVC parentVC: UIViewController, completion: (() -> ())? = nil) { + parentVC.view.endEditing(true) + + picker.delegate = self + picker.dataSource = self + setup(parentVC) + move(goUp: true) + + UIView.animate( + withDuration: config.animationDuration, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 5, options: .curveEaseIn, animations: { + + parentVC.view.layoutIfNeeded() + self.overlayButton.alpha = 1 + + }, completion: { (finished) in + completion?() + } + ) + + } + + // MARK: - Dismiss + func dismiss(_ completion: (() -> ())? = nil) { + + move(goUp: false) + + UIView.animate( + withDuration: config.animationDuration, animations: { + + self.layoutIfNeeded() + self.overlayButton.alpha = 0 + + }, completion: { (finished) in + completion?() + self.removeFromSuperview() + self.overlayButton.removeFromSuperview() + } + ) + } + + func numberOfComponents(in pickerView: UIPickerView) -> Int{ + return 1 + } + + func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{ + return config.pickerArray.count + } + + func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + // self.endEditing(true) + return config.pickerArray[row] + } + + func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { + return CGFloat(30) + } + + func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + + if !config.pickerArray.isEmpty { + pickerValue = config.pickerArray[row] + pickerRow = row + } + // delegate?.customPicker(self, didSelect: config.pickerArray[row]) + } + + func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { + let label = (view as? UILabel) ?? UILabel() + + label.textColor = .black + label.textAlignment = .center + label.font = UIFont(name: "SanFranciscoText-Light", size: 14) + + // where data is an Array of String + label.text = config.pickerArray[row] + + return label + + } +} diff --git a/TracMobility/Utilities/CustomUIPicker.xib b/TracMobility/Utilities/CustomUIPicker.xib new file mode 100644 index 0000000..27d76bc --- /dev/null +++ b/TracMobility/Utilities/CustomUIPicker.xib @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TracMobility/Utilities/Extensions&Models.swift b/TracMobility/Utilities/Extensions&Models.swift new file mode 100644 index 0000000..b8c51b4 --- /dev/null +++ b/TracMobility/Utilities/Extensions&Models.swift @@ -0,0 +1,180 @@ +// +// Extensions.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit +import SystemConfiguration +import CoreLocation + +/// `String` +extension String { + + //remove blankSpaces + func removingBlankSpaces() -> String { + return components(separatedBy: .whitespaces).joined() + } +} + +/// `Button` +extension UIButton { + + open override var isEnabled: Bool{ + didSet { + DispatchQueue.main.async { + self.alpha = self.isEnabled ? 1.0 : 0.6 + } + } + } +} + +/// `View` +extension UIView { + + @IBInspectable + var cornerRadius: CGFloat { + get { + return layer.cornerRadius + } + set { + layer.cornerRadius = newValue + } + } + + @IBInspectable + var borderWidth: CGFloat { + get { + return layer.borderWidth + } + set { + layer.borderWidth = newValue + } + } + + @IBInspectable + var borderColor: UIColor? { + get { + if let color = layer.borderColor { + return UIColor(cgColor: color) + } + return nil + } + set { + if let color = newValue { + layer.borderColor = color.cgColor + } else { + layer.borderColor = nil + } + } + } + + @IBInspectable + var shadowRadius: CGFloat { + get { + return layer.shadowRadius + } + set { + layer.shadowRadius = newValue + } + } + + @IBInspectable + var shadowOpacity: Float { + get { + return layer.shadowOpacity + } + set { + layer.shadowOpacity = newValue + } + } + + @IBInspectable + var shadowOffset: CGSize { + get { + return layer.shadowOffset + } + set { + layer.shadowOffset = newValue + } + } + + @IBInspectable + var shadowColor: UIColor? { + get { + if let color = layer.shadowColor { + return UIColor(cgColor: color) + } + return nil + } + set { + if let color = newValue { + layer.shadowColor = color.cgColor + } else { + layer.shadowColor = nil + } + } + } +} + +/// `TextField` +extension UITextField{ + func setBorderColor(_ width:CGFloat,_ color:UIColor,_ cornerRadius: CGFloat) -> Void{ + self.layer.borderColor = color.cgColor + self.layer.borderWidth = width + self.layer.cornerRadius = cornerRadius + } +} + +//MARK: ------------------------ Enum --------------------- + +/// `Sign In` +enum SignInType: String { + + case Apple = "Apple" + case Google = "Google" + case FaceBook = "Facebook" + case SignUp = "SignUp" +} + +/// `Menu Items` +enum Menu: String { + + case Rides = "Your Rides" + case Wallet = "Wallet" + case Membership = "Membership" + case FreeRides = "Get Free Rides" + case ReferAndEarn = "Refer & Earn" + case Settings = "Settings" + case Logout = "Logout" + case Version = "Version 1.0" +} + +//MARK: ------------------------ Class --------------------- + +// Internet Connection +open class Reachability { + + class func isConnectedToNetwork() -> Bool { + + var zeroAddress = sockaddr_in() + zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) + zeroAddress.sin_family = sa_family_t(AF_INET) + + let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { + $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in + SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress) + } + } + + var flags = SCNetworkReachabilityFlags() + if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) { + return false + } + let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 + let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 + + return (isReachable && !needsConnection) + } +} diff --git a/TracMobility/ViewController/.DS_Store b/TracMobility/ViewController/.DS_Store new file mode 100644 index 0000000..8d2ab44 Binary files /dev/null and b/TracMobility/ViewController/.DS_Store differ diff --git a/TracMobility/ViewController/Authentication.swift b/TracMobility/ViewController/Authentication.swift new file mode 100644 index 0000000..1a2c228 --- /dev/null +++ b/TracMobility/ViewController/Authentication.swift @@ -0,0 +1,65 @@ +// +// Authentication.swift +// TracMobility +// +// Created by Shalini on 21/02/21. +// + +import UIKit +import Auth0 + +class Authentication: NSObject { + + func signUp(completion: @escaping(Bool) -> ()) { + guard let clientInfo = plistValues(bundle: Bundle.main) else { return } + + Auth0 + .webAuth() + .scope("openid profile") + .audience("https://" + clientInfo.domain + "/userinfo") + .start { + switch $0 { + case .failure(let error): + print("Error: \(error)") + completion(false) + + case .success(let credentials): + guard let accessToken = credentials.accessToken else { return } + UserDefaults.standard.setValue(accessToken, forKey: "accessToken") + completion(true) + } + } + } + + //logout + func logout(completion: @escaping(Bool) -> ()) { + + Auth0 + .webAuth() + .clearSession(federated:false){ + completion($0) + } + } + + //get values from plist + func plistValues(bundle: Bundle) -> (clientId: String, domain: String)? { + guard + let path = bundle.path(forResource: "Auth0", ofType: "plist"), + let values = NSDictionary(contentsOfFile: path) as? [String: Any] + else { + print("Missing Auth0.plist file with 'ClientId' and 'Domain' entries in main bundle!") + return nil + } + + guard + let clientId = values["ClientId"] as? String, + let domain = values["Domain"] as? String + else { + print("Auth0.plist file at \(path) is missing 'ClientId' and/or 'Domain' entries!") + print("File currently has the following entries: \(values)") + return nil + } + return (clientId: clientId, domain: domain) + } +} + diff --git a/TracMobility/ViewController/DashboardViewController.swift b/TracMobility/ViewController/DashboardViewController.swift new file mode 100644 index 0000000..40af48d --- /dev/null +++ b/TracMobility/ViewController/DashboardViewController.swift @@ -0,0 +1,284 @@ +// +// DashboardViewController.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit +import GoogleMaps +import GooglePlaces +import CoreLocation + +class DashboardViewController: UIViewController { + + @IBOutlet weak var menuButton: UIButton! + @IBOutlet weak var inboxButton: UIButton! + @IBOutlet weak var scanToUnlock: UIButton! + @IBOutlet weak var containerView: UIView! + @IBOutlet weak var mapView: GMSMapView! + @IBOutlet weak var sideExtra: UIButton! + + @IBAction func sideExtraViewTapped(_ sender: Any) { + + UIView.animate(withDuration: 0.4, delay: 0.8, options: [.transitionFlipFromRight], animations: { DispatchQueue.main.async { self.containerView.isHidden = true + self.sideExtra.isHidden = true }}, completion: nil) + } + + @IBAction func inboxButtonTapped(_ sender: Any) { + + CustomAlertView.sharedInstance.okAlert(self, "Note", "This feature is not available at the moment!", "OK", .default, alertStyle: .alert) + } + + @IBAction func menuButtonTapped(_ sender: Any) { + + UIView.animate(withDuration: 0.4, delay: 0.8, options: [.transitionFlipFromLeft], animations: { DispatchQueue.main.async { self.containerView.isHidden = false + self.sideExtra.isHidden = false }}, completion: nil) + } + + @IBAction func scanToUnlockTapped(_ sender: Any) { + + getLocation(){ latitude, longitude, location in + + self.loadMap(latitude, longitude, location) + } + } + + var latitude: Double? + var longitude: Double? + var located_location = String() + let locationManager = CLLocationManager() + var locationMarker = GMSMarker() + var markerIcon = UIImage() + + override func viewDidLoad() { + super.viewDidLoad() + + DispatchQueue.main.async { + self.sideExtra.isHidden = true + self.containerView.isHidden = true + } + self.containerView.layer.masksToBounds = true + + /// `check location permission` + guard locationPermission() else { + + self.locationPermissionAlert("TracMobility does not have access to your location. To enable access, tap Settings and turn on location.") + return + } + + mapView.isMyLocationEnabled = true + mapView.settings.myLocationButton = true + + //start location + startTrackingLocation() + getLocation(){ latitude, longitude, location in + + self.loadMap(latitude, longitude, location) + } + + //set up marker + if let image = UIImage(named: "Marker") { + markerIcon = resizeImage(image: image, targetSize: CGSize.init(width: 50, height: 50)) + } + } + + override func viewWillDisappear(_ animated: Bool) { + + NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) + } + + //resize the image + func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage { + let size = image.size + + let widthRatio = targetSize.width / image.size.width + let heightRatio = targetSize.height / image.size.height + + // Figure out what our orientation is, and use that to form the rectangle + var newSize: CGSize + if(widthRatio > heightRatio) { + newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio) + } else { + newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio) + } + + // This is the rect that we've calculated out and this is what is actually used below + let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height) + + // Actually do the resizing to the rect using the ImageContext stuff + UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0) + image.draw(in: rect) + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return newImage ?? UIImage() + } + + //loadMap + func loadMap(_ latitude: Double?,_ longitude: Double?,_ location: String?) { + + DispatchQueue.main.async { [self] in + + let camera = GMSCameraPosition.camera(withLatitude: latitude ?? 0.0, longitude: longitude ?? 0.0, zoom: 14) + self.mapView.animate(to: camera) + + self.locationMarker.position = CLLocationCoordinate2D(latitude: latitude ?? 0.0, longitude: longitude ?? 0.0) + + self.locationMarker.title = location + self.locationMarker.icon = .some(self.markerIcon) + self.locationMarker.appearAnimation = .pop + self.locationMarker.map = self.mapView + } + } +} + +//MARK: `Location Permission & Delegates` +extension DashboardViewController: CLLocationManagerDelegate { + + //init location manager + func startTrackingLocation() { + + locationManager.delegate = self + locationManager.desiredAccuracy = kCLLocationAccuracyBest + locationManager.requestLocation() + locationManager.startUpdatingLocation() + } + + //get latitude, longitude and location + func getLocation(completion: @escaping (_ latitude: Double?,_ longitude: Double?,_ location: String?) -> ()) { + + let coordinate = CLLocation(latitude: self.latitude ?? 0.0, longitude: self.longitude ?? 0.0) + geoCoder(coordinate) { + completion(self.latitude, self.longitude, self.located_location) + } + } + + //stop tracking the location + func stopTracking() { + locationManager.stopUpdatingLocation() + } + + //location permission + func locationPermission() -> Bool { + + if CLLocationManager.locationServicesEnabled() { + let locationStatus = CLLocationManager.authorizationStatus() + + switch locationStatus { + case .authorized, .authorizedWhenInUse: + NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) + return true + + case .restricted,.denied: + stopTracking() + NotificationCenter.default.addObserver(self, selector: #selector(self.checkPermissionForeground), name: UIApplication.willEnterForegroundNotification, object: nil) + return false + + case .notDetermined: + locationManager.delegate = self + locationManager.requestWhenInUseAuthorization() + + NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) + + return true + + default: + return false + } + } + return false + } + + @objc func checkPermissionForeground() { + + DispatchQueue.main.async(execute: { + + if !self.locationPermission() { + self.locationPermissionAlert("TracMobility does not have access to your location. To enable access, tap Settings and turn on location.") + } + }) + } + + //if the permission is denied, redirect to settings. + func locationPermissionAlert(_ titleText: String){ + let alertController = UIAlertController(title: titleText, message: nil, preferredStyle: .alert) + + let settingsAction = UIAlertAction(title: "Settings", style: .default){ (_) -> Void in + if let url = URL(string: UIApplication.openSettingsURLString) { + if #available(iOS 10, *) { + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } else { + UIApplication.shared.openURL(url as URL) + } + } + } + alertController.addAction(settingsAction) + + let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + alertController.addAction(cancel) + + OperationQueue.main.addOperation { + self.present(alertController, animated: true, completion:nil) + } + } + + func geoCoder(_ coordinate: CLLocation, completion: @escaping() ->()) { + + let geocoder: CLGeocoder = CLGeocoder() + geocoder.reverseGeocodeLocation(coordinate, completionHandler: {(response, error) -> Void in + + if let address = response?.first { + + if address.subLocality != nil && address.locality != nil && address.country != nil { + self.located_location = "\(address.subLocality!), " + "\(address.locality!), " + "\(address.country!)" + } else if address.locality != nil && address.country != nil { + self.located_location = "\(address.locality!), " + "\(address.country!)" + } else if address.locality != nil { + self.located_location = address.locality! + } else { + self.located_location = "" + } + completion() + } + }) + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + + let userCllocation = locations[0] as CLLocation + latitude = userCllocation.coordinate.latitude + longitude = userCllocation.coordinate.longitude + + let coordinate = CLLocation(latitude: self.latitude ?? 0.0, longitude: self.longitude ?? 0.0) + geoCoder(coordinate) { } + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + checkPermissionForeground() + } +} + +//MARK: `Map Delegates` +extension DashboardViewController: GMSMapViewDelegate { + + func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { + + locationMarker = marker + return false + } + + func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { + } + + // take care of the close event + func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { + latitude = coordinate.latitude + longitude = coordinate.longitude + + getLocation(){ latitude, longitude, location in + + self.loadMap(latitude, longitude, location) + } + } +} diff --git a/TracMobility/ViewController/LaunchScreenViewController.swift b/TracMobility/ViewController/LaunchScreenViewController.swift new file mode 100644 index 0000000..98ce793 --- /dev/null +++ b/TracMobility/ViewController/LaunchScreenViewController.swift @@ -0,0 +1,47 @@ +// +// LaunchScreenViewController.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +class LaunchScreenViewController: UIViewController { + + @IBOutlet weak var tracMobilityLogo: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + + /// `Animate the launch screen` + UIView.animate(withDuration: 0.4, delay: 0.8, options: [.curveEaseIn], animations: { + + let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.x") + rotation.toValue = NSNumber(value: Double.pi * 2) + rotation.duration = 1.2 + rotation.repeatCount = 1 + self.tracMobilityLogo.layer.add(rotation, forKey: "rotationAnimation") + + }, completion: {_ in + + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.2) { + + if UserDefaults.standard.value(forKey: "accessToken") != nil { + + // redirect to dashboard if user already logged In + let storyboard = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "DashboardViewControllerID") as! DashboardViewController + storyboard.modalPresentationStyle = .fullScreen + self.present(storyboard, animated: true) + + } else { + + // redirect the user to sign up screen + let storyboard = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "navigationControllerID") as! UINavigationController + storyboard.modalPresentationStyle = .fullScreen + self.present(storyboard, animated: true, completion:nil) + } + } + }) + } +} diff --git a/TracMobility/ViewController/SceneDelegate.swift b/TracMobility/ViewController/SceneDelegate.swift new file mode 100644 index 0000000..7aa73a0 --- /dev/null +++ b/TracMobility/ViewController/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/TracMobility/ViewController/SideInViewController.swift b/TracMobility/ViewController/SideInViewController.swift new file mode 100644 index 0000000..01fe520 --- /dev/null +++ b/TracMobility/ViewController/SideInViewController.swift @@ -0,0 +1,117 @@ +// +// SideInViewController.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +class SideInViewController: UIViewController { + + @IBOutlet weak var userName: UILabel! + @IBOutlet weak var emailID: UILabel! + @IBOutlet weak var mobileNumber: UILabel! + @IBOutlet weak var userImage: UIImageView! + @IBOutlet weak var sideMenuTableView: UITableView! + + var menuItems:[Menu] = [.Rides, .Wallet, .Membership, .FreeRides, .ReferAndEarn, .Settings , .Version, .Logout] + + override func viewDidLoad() { + super.viewDidLoad() + + self.sideMenuTableView.tableFooterView = UIView() + if let userInfo = UserDefaults.standard.value(forKey: "userInfo") as? [String : String] { + userName.text = "\((userInfo["FirstName"] ?? "Trac Mobility") + " " + (userInfo["LastName"] ?? ""))" + mobileNumber.text = "\((userInfo["CountryCode"] ?? "🇬🇧+44") + " " + (userInfo["PhoneNumber"] ?? "7743405150"))" + emailID.text = userInfo["Email"] ?? "tracmobility@gmail.com" + } + } + + override func viewWillAppear(_ animated: Bool) { + self.sideMenuTableView.reloadData() + } + + /// `LogOut` + func logOutTapped() { + + + let confirmationAlert = UIAlertController(title: "Are you sure", message: "You want to logout?", preferredStyle: .alert) + + let confirmDelete = UIAlertAction(title: "Logout", style: .destructive) { _ in + +// Authentication().logout { done in +// if done { + + /// `Delete stored user Info & access token` + UserDefaults.standard.removeObject(forKey: "userInfo") + UserDefaults.standard.removeObject(forKey: "accessToken") + + DispatchQueue.main.async { + + // redirect the user to sign up screen + let storyboard = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "navigationControllerID") as! UINavigationController + storyboard.modalPresentationStyle = .fullScreen + self.present(storyboard, animated: true, completion:nil) + } +// } else { +// CustomAlertView.sharedInstance.okAlert(self, "Error", "Sorry, something went wrong. Please try after some time!", "OK", .default, alertStyle: .alert) +// } + } + confirmationAlert.addAction(confirmDelete) + + let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + confirmationAlert.addAction(cancel) + + OperationQueue.main.addOperation { + self.present(confirmationAlert, animated: true) + } + } +} + +//MARK: `UITableview Delegates` +extension SideInViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return menuItems.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) + + let menu = menuItems[indexPath.row] + cell.textLabel?.text = menu.rawValue + + cell.accessoryType = .disclosureIndicator + cell.textLabel?.textAlignment = .left + cell.textLabel?.textColor = UIColor.black + + if menu.rawValue == Menu.Logout.rawValue { + + cell.accessoryType = .none + cell.textLabel?.textAlignment = .center + cell.textLabel?.textColor = UIColor.red + + //tap gesture for logout + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didSelect)) + cell.tag = indexPath.row + cell.addGestureRecognizer(tapGesture) + + } else if menu.rawValue == Menu.Version.rawValue { + cell.accessoryType = .none + } + + return cell + } + + @objc func didSelect(tapGesture: UITapGestureRecognizer) { + + let indexPath = IndexPath(row: (tapGesture.view?.tag ?? 0), section:0) + let menu = menuItems[indexPath.row] + if menu.rawValue == Menu.Logout.rawValue { + logOutTapped() + } + } +} + diff --git a/TracMobility/ViewController/SignUpViewController.swift b/TracMobility/ViewController/SignUpViewController.swift new file mode 100644 index 0000000..2fc72d1 --- /dev/null +++ b/TracMobility/ViewController/SignUpViewController.swift @@ -0,0 +1,455 @@ +// +// SignUpViewController.swift +// TracMobility +// +// Created by Shalini on 20/02/21. +// + +import UIKit + +class SignUpViewController: UIViewController { + + @IBOutlet weak var firstNameTextField: UITextField! + @IBOutlet weak var lastNameTextField: UITextField! + @IBOutlet weak var emailAddressTextField: UITextField! + @IBOutlet weak var phoneNumberTextField: UITextField! + @IBOutlet weak var countryCode: UITextField! + + @IBOutlet weak var signUpButton: UIButton! + @IBOutlet weak var appleButton: UIButton! + @IBOutlet weak var googleButton: UIButton! + @IBOutlet weak var facebookButton: UIButton! + + @IBAction func firstNameButtonTapped(_ sender: Any) { + _ = isValidName(firstNameTextField) //validate the first name + _ = enableSubmit() //check for enable/disable submit + } + + @IBAction func lastNameButtonTapped(_ sender: Any) { + _ = isValidName(lastNameTextField) //validate the last name + _ = enableSubmit() //check for enable/disable submit + } + + @IBAction func emailButtonTapped(_ sender: Any) { + _ = isValidEmail() //validate the email Id + _ = enableSubmit() //check for enable/disable submit + } + + @IBAction func mobileNumberButtonTapped(_ sender: Any) { + _ = isValidPhoneNumber() //validate the phone number + _ = enableSubmit() //check for enable/disable submit + } + + @IBAction func signUpButtonTapped(_ sender: Any) { + + //check for enable/disable submit + if enableSubmit() { + self.signupButtonTapped(.SignUp) + } + } + + @IBAction func appleButtonTapped(_ sender: Any) { + self.signupButtonTapped(.Apple) + } + + @IBAction func googleButtonTapped(_ sender: Any) { + self.signupButtonTapped(.Google) + } + + @IBAction func facebookButtonTapped(_ sender: Any) { + self.signupButtonTapped(.FaceBook) + } + + var returnButton = UIButton() + var defaultCountryCode = "🇬🇧+44" + lazy var countryCodeArray = [String]() + lazy var picker = CustomUIPicker.getFromNib() + + override func viewDidLoad() { + super.viewDidLoad() + + self.signUpButton.isEnabled = false + + //tap gesture for view + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture)) + view.addGestureRecognizer(tapGesture) + + //tap gesture for textField + let textFieldTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTextField)) + countryCode.addGestureRecognizer(textFieldTapGesture) + + //custom return button + returnButton.setTitle("Return", for: UIControl.State()) + returnButton.setTitleColor(UIColor.black, for: UIControl.State()) + returnButton.frame = CGRect(x: 0, y: 163, width: 106, height: 53) + returnButton.addTarget(self, action: #selector(returnButtonTapped), for: UIControl.Event.touchUpInside) + + //get current country code + getCountryBasedTimeZone() { + (countryName, countryCode, countryFlag) in + + self.defaultCountryCode = "\(countryFlag ?? "🇬🇧")\(countryCode ?? "+44")" + self.countryCode.text = self.defaultCountryCode + } + } + + override func viewDidDisappear(_ animated: Bool) { + + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) + } + + @objc func handleTapGesture(tapGesture: UITapGestureRecognizer) { + + _ = enableSubmit() //check for enable/disable submit + view.endEditing(true) //dismiss the keyboard + } + + @objc func handleTextField(tapGesture: UITapGestureRecognizer) { + + if countryCodeArray.isEmpty { + + getCountryBasedTimeZone() { + (_, _, _) in + + let countryCode_Array = self.countryCodeArray.map({$0.components(separatedBy: "_").joined()}) + + let selectedRow = (self.countryCodeArray.map({$0.components(separatedBy: "_").first})).firstIndex(of: "\(self.countryCode.text ?? self.defaultCountryCode)") ?? 0 + self.customPicker(countryCode_Array, selectedRow) + + } + } else { + + let countryCode_Array = self.countryCodeArray.map({$0.components(separatedBy: "_").joined()}) + + let selectedRow = (self.countryCodeArray.map({$0.components(separatedBy: "_").first})).firstIndex(of: "\(self.countryCode.text ?? self.defaultCountryCode)") ?? 0 + self.customPicker(countryCode_Array, selectedRow) + } + } + + //return button tapped for mobile number keyboard + @objc func returnButtonTapped() { + phoneNumberTextField.resignFirstResponder() + view.endEditing(true) + } + + @objc func keyboardWillHide(_ note : Notification) -> Void{ + DispatchQueue.main.async { () -> Void in + self.returnButton.isHidden = true + } + } + + //name validation + func isValidName(_ nameTextField: UITextField) -> Bool { + if nameTextField.text != nil { + + let nameRegEx = "^[a-zA-Z]*['.-]?[a-zA-Z]+['.]?$" + let nameTest = NSPredicate(format:"SELF MATCHES %@", nameRegEx) + + if nameTest.evaluate(with: nameTextField.text?.removingBlankSpaces()) { + return updateValidView(nameTextField) + } else { + return updateErrorView(nameTextField) + } + } + return false + } + + //email validation + func isValidEmail() -> Bool { + + if emailAddressTextField.text != nil { + let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,3}" + let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) + + if emailTest.evaluate(with: emailAddressTextField.text!) { + return updateValidView(emailAddressTextField) + } else { + return updateErrorView(emailAddressTextField) + } + } + return false + } + + //phone number validation + func isValidPhoneNumber() -> Bool{ + + if phoneNumberTextField.text != nil { + if phoneNumberTextField.text?.count ?? 0 < 7 { + return updateErrorView(phoneNumberTextField) + } else { + return updateValidView(phoneNumberTextField) + } + } + return false + } + + //update the view with valid prompt + func updateValidView(_ textField: UITextField) -> Bool { + + textField.setBorderColor(0.0, UIColor.lightGray, 5.0) + view.setNeedsLayout() + view.layoutIfNeeded() + + return true + } + + //update the view with error prompt + func updateErrorView(_ textField: UITextField) -> Bool { + + textField.setBorderColor(0.5, UIColor.red, 5.0) + view.setNeedsLayout() + view.layoutIfNeeded() + + return false + } + + //disable the keyboard for country code + func disableKeyboard(_ textField: UITextField) -> Bool { + if textField == countryCode { + countryCode.resignFirstResponder() + return false + } + return true + } + + //enable/disable submit button + func enableSubmit() -> Bool { + + if (!(firstNameTextField.text?.removingBlankSpaces().isEmpty)!) && (!(lastNameTextField.text?.removingBlankSpaces().isEmpty)!) && (!(emailAddressTextField.text?.removingBlankSpaces().isEmpty)!) && (!(phoneNumberTextField.text?.removingBlankSpaces().isEmpty)!) { + + if isValidName(firstNameTextField) && isValidName(lastNameTextField) && isValidEmail() && isValidPhoneNumber() { + DispatchQueue.main.async { self.signUpButton.isEnabled = true } + return true + } + return false + } else { + DispatchQueue.main.async { self.signUpButton.isEnabled = false } + return false + } + } +} + +//MARK: `Sign Up / Sign In with Facebook, Google, Apple ` +extension SignUpViewController { + + //sign up + func signupButtonTapped(_ type: SignInType) { + + if Reachability.isConnectedToNetwork() { + + if type == .SignUp { + + /// `Normal sign up` + successSignUp() + + } else { + + //present and start the activity indicator + DispatchQueue.main.async { + CustomActivityIndicator.sharedInstance.presentActivityIndicator(self) + CustomActivityIndicator.sharedInstance.startAnimating(self) + self.signUpButton.isEnabled = false } + + /// `Google, Facebook, Apple` + Authentication().signUp { success in + + DispatchQueue.main.async { self.signUpButton.isEnabled = true + CustomActivityIndicator.sharedInstance.stopAnimating(self) } + + if success { + + self.successSignUp() + } else { + CustomAlertView.sharedInstance.okAlert(self, "Error", "Sorry, something went wrong. Please try after some time!", "OK", .default, alertStyle: .alert) + } + } + } + } else { + + //no internet pop up + DispatchQueue.main.async { self.signUpButton.isEnabled = true + CustomActivityIndicator.sharedInstance.stopAnimating(self) } + CustomAlertView.sharedInstance.okAlert(self, "No Internet Connection", "Make sure your device is connected to the internet.", "OK", .default, alertStyle: .alert) + } + } + + func successSignUp() { + + let alert = UIAlertController(title: "Signed up successfully", message: nil, preferredStyle: .actionSheet) + self.present(alert, animated: true) + + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0){ + alert.dismiss(animated: true, completion: nil) + + /// `Save the user Information` + let userDict:Dictionary = ["FirstName": self.firstNameTextField.text ?? "Trac Mobility", "LastName": self.lastNameTextField.text ?? "", "Email": self.emailAddressTextField.text ?? "tracmobility@gmail.com", "CountryCode": self.countryCode.text ?? self.defaultCountryCode, "PhoneNumber": self.phoneNumberTextField.text ?? "7743405150"] + UserDefaults.standard.set(userDict, forKey: "userInfo") + + let storyboard = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "DashboardViewControllerID") as! DashboardViewController + storyboard.modalPresentationStyle = .fullScreen + + self.navigationController?.pushViewController(storyboard, animated: true) + } + } +} + +//MARK: `UITextField Delegates` +extension SignUpViewController: UITextFieldDelegate { + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + + guard let text = textField.text else { return true } + let newLength = text.count + string.count - range.length + + //character limit + switch textField { + case firstNameTextField, lastNameTextField: return newLength <= 150 + case emailAddressTextField: return newLength <= 120 + case phoneNumberTextField: return newLength < 15 + + default: + return true + } + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + + //moving the cursor one after the other textfield + switch textField { + case firstNameTextField: lastNameTextField.becomeFirstResponder() + case lastNameTextField: emailAddressTextField.becomeFirstResponder() + case emailAddressTextField: phoneNumberTextField.becomeFirstResponder() + case phoneNumberTextField: textField.resignFirstResponder() + default: + textField.resignFirstResponder() + } + + //check for enable/disable submit + _ = enableSubmit() + return true + } + + func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { + + if textField == phoneNumberTextField { + DispatchQueue.main.async { () -> Void in + self.returnButton.isHidden = false + let keyBoardWindow = UIApplication.shared.windows.last + self.returnButton.frame = CGRect(x: 0, y: (keyBoardWindow?.frame.size.height)!-53, width: 106, height: 53) + keyBoardWindow?.addSubview(self.returnButton) + keyBoardWindow?.bringSubviewToFront(self.returnButton) + } + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) + } else { + DispatchQueue.main.async { self.returnButton.isHidden = true } + } + return disableKeyboard(textField) + } + + func textFieldDidBeginEditing(_ textField: UITextField) { + _ = disableKeyboard(textField) + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + + if textField == firstNameTextField || textField == lastNameTextField { + _ = isValidName(textField) + + } else if textField == emailAddressTextField { + _ = isValidEmail() + + } else if textField == phoneNumberTextField { + _ = isValidPhoneNumber() + } + return disableKeyboard(textField) + } + + func textFieldDidEndEditing(_ textField: UITextField) { + _ = disableKeyboard(textField) + } +} + +//MARK: `UIPicker Delegates` +extension SignUpViewController: CustomUIPickerDelegate { + + //get country name and flag based on time zone + func getCountryBasedTimeZone(completion: @escaping (_ countryName: String?,_ countryCode: String?,_ countryFlag: String?) -> ()) { + + let url = Bundle.main.url(forResource: "Countries", withExtension: "json") + let data = NSData(contentsOf: url!) + + do { + let object = try JSONSerialization.jsonObject(with: data! as Data, options: .allowFragments) + if let dictionary = object as? [String: AnyObject] { + guard let countryJsonObject = dictionary["countryPick"] as? [[String: AnyObject]] else { return } + + if countryCodeArray.isEmpty { + for countries in countryJsonObject { + let flagCharacter = countries["code"] as? String ?? "GB" + let name = countries["name"] as? String ?? "United Kingdom" + let code = countries["dial_code"] as? String ?? "+44" + + let emoji = getEmojiFromCharacter(countryCode: flagCharacter); + let flagString = String(emoji); + + self.countryCodeArray.append("\(flagString)\(code)_ \(name)") + self.countryCode.text = "\(flagString)\(code)" + } + } + + //fetch default country code + let countryCode = (Locale.current as NSLocale).object(forKey: .countryCode) as? String + let country = countryJsonObject.filter({$0["code"] as? String == countryCode}).first + + let emoji = getEmojiFromCharacter(countryCode: country?["code"] as? String ?? "GB"); + let flagString = String(emoji) + completion(country?["name"] as? String ?? "United Kingdom", country?["dial_code"] as? String ?? "+44", flagString) + + } + } catch { + // Handle Error + } + } + + //get country flag + public func getEmojiFromCharacter(countryCode: String) -> Character { + let base = UnicodeScalar("🇦").value - UnicodeScalar("A").value + + var string = "" + countryCode.uppercased().unicodeScalars.forEach { + if let scala = UnicodeScalar(base + $0.value) { + string.append(String(describing: scala)) + } + } + return Character(string) + } + + //ui picker + func customPicker(_ pickerArray: [String],_ selectedRow: Int) { + picker.delegate = self + + picker.pickerRow = nil + picker.pickerValue = nil + picker.config.animationDuration = 0.25 + picker.config.pickerArray = pickerArray + picker.config.selectedRow = selectedRow + print(selectedRow) + + picker.show(inVC: self) + } + + func customPicker(_ amPicker: CustomUIPicker, didSelect row: Int, value: String) { + + let country_Code = value + let code = country_Code.components(separatedBy: " ").first ?? "" + self.countryCode.text = code + } + + func customPickerDidCancelSelection(_ amPicker: CustomUIPicker) { + print("cancel") + } +} diff --git a/screenshots/IMG_3353.PNG b/screenshots/IMG_3353.PNG new file mode 100644 index 0000000..f025e55 Binary files /dev/null and b/screenshots/IMG_3353.PNG differ diff --git a/screenshots/IMG_3354.PNG b/screenshots/IMG_3354.PNG new file mode 100644 index 0000000..329e063 Binary files /dev/null and b/screenshots/IMG_3354.PNG differ diff --git a/screenshots/IMG_3355.PNG b/screenshots/IMG_3355.PNG new file mode 100644 index 0000000..48c3650 Binary files /dev/null and b/screenshots/IMG_3355.PNG differ diff --git a/screenshots/IMG_3356.PNG b/screenshots/IMG_3356.PNG new file mode 100644 index 0000000..3c18da8 Binary files /dev/null and b/screenshots/IMG_3356.PNG differ diff --git a/screenshots/IMG_3358.PNG b/screenshots/IMG_3358.PNG new file mode 100644 index 0000000..8aa4741 Binary files /dev/null and b/screenshots/IMG_3358.PNG differ diff --git a/screenshots/IMG_3359.PNG b/screenshots/IMG_3359.PNG new file mode 100644 index 0000000..45f1ad2 Binary files /dev/null and b/screenshots/IMG_3359.PNG differ diff --git a/screenshots/IMG_3360.PNG b/screenshots/IMG_3360.PNG new file mode 100644 index 0000000..bd697f0 Binary files /dev/null and b/screenshots/IMG_3360.PNG differ diff --git a/screenshots/IMG_3362.PNG b/screenshots/IMG_3362.PNG new file mode 100644 index 0000000..222d776 Binary files /dev/null and b/screenshots/IMG_3362.PNG differ diff --git a/screenshots/IMG_3364.PNG b/screenshots/IMG_3364.PNG new file mode 100644 index 0000000..439591c Binary files /dev/null and b/screenshots/IMG_3364.PNG differ diff --git a/screenshots/IMG_3365.PNG b/screenshots/IMG_3365.PNG new file mode 100644 index 0000000..c483361 Binary files /dev/null and b/screenshots/IMG_3365.PNG differ diff --git a/screenshots/RPReplay_Final1613921491.mov b/screenshots/RPReplay_Final1613921491.mov new file mode 100644 index 0000000..3ea9cba Binary files /dev/null and b/screenshots/RPReplay_Final1613921491.mov differ