diff --git a/Podfile b/Podfile index 228a999..5be9b38 100644 --- a/Podfile +++ b/Podfile @@ -15,6 +15,8 @@ target 'WOKA' do pod 'CollectionViewCenteredFlowLayout' + pod 'SDWebImage' + # Bottom line is for removing IPHONEOS_DEPLOYMENT_TARGET post_install do |installer| installer.generated_projects.each do |project| diff --git a/WOKA.xcodeproj/project.pbxproj b/WOKA.xcodeproj/project.pbxproj index 4ac6cf2..c9f4732 100644 --- a/WOKA.xcodeproj/project.pbxproj +++ b/WOKA.xcodeproj/project.pbxproj @@ -29,7 +29,6 @@ 525954192BE8CC3400191286 /* ConstantString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954182BE8CC3400191286 /* ConstantString.swift */; }; 5259541B2BE8D6F900191286 /* NetworkReachibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5259541A2BE8D6F900191286 /* NetworkReachibility.swift */; }; 5259541D2BE8D94400191286 /* QueueHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5259541C2BE8D94400191286 /* QueueHelper.swift */; }; - 5259541F2BE8E93500191286 /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 5259541E2BE8E93500191286 /* Config.xcconfig */; }; 525954212BE8EB7900191286 /* APIEndPoints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954202BE8EB7900191286 /* APIEndPoints.swift */; }; 525954232BE8F00400191286 /* BaseResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954222BE8F00400191286 /* BaseResponseModel.swift */; }; 525954252BE8F01600191286 /* ValueWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954242BE8F01600191286 /* ValueWrapper.swift */; }; @@ -40,6 +39,16 @@ 525954302BEA394400191286 /* CustomAlerts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5259542F2BEA394300191286 /* CustomAlerts.storyboard */; }; 525954322BEA39D200191286 /* AddTapGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954312BEA39D200191286 /* AddTapGesture.swift */; }; 525954342BEA620800191286 /* IntrestTopicDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954332BEA620800191286 /* IntrestTopicDM.swift */; }; + 525954352BEB4B3B00191286 /* Exo2-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8312BDBC3EF00E4CA14 /* Exo2-Thin.ttf */; }; + 525954362BEB4B3B00191286 /* Exo2-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E82F2BDBC3EF00E4CA14 /* Exo2-Medium.ttf */; }; + 525954372BEB4B3B00191286 /* Exo2-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E82E2BDBC3EF00E4CA14 /* Exo2-Bold.ttf */; }; + 525954382BEB4B3B00191286 /* Exo2-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8332BDBC3EF00E4CA14 /* Exo2-Regular.ttf */; }; + 525954392BEB4B3B00191286 /* Exo2-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8322BDBC3EF00E4CA14 /* Exo2-ExtraBold.ttf */; }; + 5259543A2BEB4B3B00191286 /* Exo2-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8302BDBC3EF00E4CA14 /* Exo2-SemiBold.ttf */; }; + 525954512BEB5EB700191286 /* SkeletonView in Frameworks */ = {isa = PBXBuildFile; productRef = 525954502BEB5EB700191286 /* SkeletonView */; }; + 5259545A2BEB67D200191286 /* DateFormatterLib.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525954592BEB67D200191286 /* DateFormatterLib.swift */; }; + 5259545C2BEBB80400191286 /* AvatarDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5259545B2BEBB80400191286 /* AvatarDM.swift */; }; + 5259545E2BEBBA1A00191286 /* LoadingIndicatorImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5259545D2BEBBA1A00191286 /* LoadingIndicatorImageView.swift */; }; 52663FF52BDFAB830001D8CE /* TextFieldErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52663FF42BDFAB830001D8CE /* TextFieldErrorView.swift */; }; 52663FF72BDFACF60001D8CE /* ShadowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52663FF62BDFACF60001D8CE /* ShadowView.swift */; }; 52663FF92BDFAF110001D8CE /* EmailVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52663FF82BDFAF110001D8CE /* EmailVM.swift */; }; @@ -85,12 +94,6 @@ 9C27E16F2BDB866500EC1DA9 /* CellIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E16E2BDB866500EC1DA9 /* CellIdentifier.swift */; }; 9C27E1722BDB86B600EC1DA9 /* OnBoardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E1702BDB86B600EC1DA9 /* OnBoardCell.swift */; }; 9C27E1732BDB86B600EC1DA9 /* OnBoardCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9C27E1712BDB86B600EC1DA9 /* OnBoardCell.xib */; }; - 9C56E8342BDBC3F000E4CA14 /* Exo2-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E82E2BDBC3EF00E4CA14 /* Exo2-Bold.ttf */; }; - 9C56E8352BDBC3F000E4CA14 /* Exo2-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E82F2BDBC3EF00E4CA14 /* Exo2-Medium.ttf */; }; - 9C56E8362BDBC3F000E4CA14 /* Exo2-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8302BDBC3EF00E4CA14 /* Exo2-SemiBold.ttf */; }; - 9C56E8372BDBC3F000E4CA14 /* Exo2-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8312BDBC3EF00E4CA14 /* Exo2-Thin.ttf */; }; - 9C56E8382BDBC3F000E4CA14 /* Exo2-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8322BDBC3EF00E4CA14 /* Exo2-ExtraBold.ttf */; }; - 9C56E8392BDBC3F000E4CA14 /* Exo2-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8332BDBC3EF00E4CA14 /* Exo2-Regular.ttf */; }; 9C56E83B2BDBC6E600E4CA14 /* SelectAgeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56E83A2BDBC6E600E4CA14 /* SelectAgeVM.swift */; }; 9C56E8462BDBEE6400E4CA14 /* EmailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56E8452BDBEE6400E4CA14 /* EmailVC.swift */; }; 9C56E8482BDBEFAB00E4CA14 /* AssetColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56E8472BDBEFAB00E4CA14 /* AssetColor.swift */; }; @@ -163,6 +166,9 @@ 5259542F2BEA394300191286 /* CustomAlerts.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = CustomAlerts.storyboard; sourceTree = ""; }; 525954312BEA39D200191286 /* AddTapGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTapGesture.swift; sourceTree = ""; }; 525954332BEA620800191286 /* IntrestTopicDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntrestTopicDM.swift; sourceTree = ""; }; + 525954592BEB67D200191286 /* DateFormatterLib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatterLib.swift; sourceTree = ""; }; + 5259545B2BEBB80400191286 /* AvatarDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarDM.swift; sourceTree = ""; }; + 5259545D2BEBBA1A00191286 /* LoadingIndicatorImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingIndicatorImageView.swift; sourceTree = ""; }; 52663FF42BDFAB830001D8CE /* TextFieldErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldErrorView.swift; sourceTree = ""; }; 52663FF62BDFACF60001D8CE /* ShadowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowView.swift; sourceTree = ""; }; 52663FF82BDFAF110001D8CE /* EmailVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailVM.swift; sourceTree = ""; }; @@ -241,6 +247,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 525954512BEB5EB700191286 /* SkeletonView in Frameworks */, 619A5A1BD8BD968ADC83C106 /* Pods_WOKA.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -486,6 +493,8 @@ 52D774F02BDFC53B001D87DE /* StringSubScript.swift */, 52C6E01D2BE3847F00E22D59 /* BorderView.swift */, 525954312BEA39D200191286 /* AddTapGesture.swift */, + 525954592BEB67D200191286 /* DateFormatterLib.swift */, + 5259545D2BEBBA1A00191286 /* LoadingIndicatorImageView.swift */, ); path = Helpers; sourceTree = ""; @@ -575,6 +584,7 @@ 525954282BEA079500191286 /* UserEmailVerifyDM.swift */, 5259542A2BEA292800191286 /* UserRegPostModel.swift */, 525954332BEA620800191286 /* IntrestTopicDM.swift */, + 5259545B2BEBB80400191286 /* AvatarDM.swift */, ); path = Model; sourceTree = ""; @@ -655,6 +665,7 @@ ); name = WOKA; packageProductDependencies = ( + 525954502BEB5EB700191286 /* SkeletonView */, ); productName = WOKA; productReference = 523ED25A2BDA2BC700CFED02 /* WOKA.app */; @@ -730,6 +741,7 @@ ); mainGroup = 523ED2512BDA2BC700CFED02; packageReferences = ( + 5259544F2BEB5EB700191286 /* XCRemoteSwiftPackageReference "SkeletonView" */, ); productRefGroup = 523ED25B2BDA2BC700CFED02 /* Products */; projectDirPath = ""; @@ -753,20 +765,19 @@ 9CBCB2A82BE5105A007D7934 /* Home.storyboard in Resources */, 525954302BEA394400191286 /* CustomAlerts.storyboard in Resources */, 52C8B0632BDA6993003B51D0 /* Localizable.strings in Resources */, - 9C56E8382BDBC3F000E4CA14 /* Exo2-ExtraBold.ttf in Resources */, - 9C56E8372BDBC3F000E4CA14 /* Exo2-Thin.ttf in Resources */, - 9C56E8352BDBC3F000E4CA14 /* Exo2-Medium.ttf in Resources */, - 9C56E8342BDBC3F000E4CA14 /* Exo2-Bold.ttf in Resources */, 523ED2672BDA2BC900CFED02 /* Assets.xcassets in Resources */, 523ED26A2BDA2BC900CFED02 /* Base in Resources */, 52C8B05B2BDA5924003B51D0 /* WokaSplashSound.m4a in Resources */, + 525954352BEB4B3B00191286 /* Exo2-Thin.ttf in Resources */, + 525954362BEB4B3B00191286 /* Exo2-Medium.ttf in Resources */, + 525954372BEB4B3B00191286 /* Exo2-Bold.ttf in Resources */, + 525954382BEB4B3B00191286 /* Exo2-Regular.ttf in Resources */, + 525954392BEB4B3B00191286 /* Exo2-ExtraBold.ttf in Resources */, + 5259543A2BEB4B3B00191286 /* Exo2-SemiBold.ttf in Resources */, 523ED2652BDA2BC700CFED02 /* Base in Resources */, 52C6E01C2BE383C000E22D59 /* YourIntrestCell.xib in Resources */, - 5259541F2BE8E93500191286 /* Config.xcconfig in Resources */, - 9C56E8392BDBC3F000E4CA14 /* Exo2-Regular.ttf in Resources */, 52C6E0262BE3B46A00E22D59 /* SelectAvatarCell.xib in Resources */, 52C8B0712BDA7512003B51D0 /* PassingCloud.json in Resources */, - 9C56E8362BDBC3F000E4CA14 /* Exo2-SemiBold.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -838,9 +849,11 @@ 525954102BE8B72900191286 /* FontCustom.swift in Sources */, 5202AAFE2BDF90590043B7BD /* TextFieldImage.swift in Sources */, 52C6E0232BE3B3E300E22D59 /* SelectAvatarVC.swift in Sources */, + 5259545C2BEBB80400191286 /* AvatarDM.swift in Sources */, 52C8B06C2BDA6E87003B51D0 /* LocalizedString.swift in Sources */, 525953D42BE8B2DF00191286 /* UIApplication.swift in Sources */, 52CC38C32BDF812F00B74C3E /* LocalisedElements.swift in Sources */, + 5259545E2BEBBA1A00191286 /* LoadingIndicatorImageView.swift in Sources */, 52CA28FC2BE11A0400708B49 /* UserIntrestVM.swift in Sources */, 9C27E1602BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift in Sources */, 5259541D2BE8D94400191286 /* QueueHelper.swift in Sources */, @@ -872,6 +885,7 @@ 52CA28FA2BE119F500708B49 /* UserIntrestVC.swift in Sources */, 9C27E16B2BDB774D00EC1DA9 /* CarouselData.swift in Sources */, 525954212BE8EB7900191286 /* APIEndPoints.swift in Sources */, + 5259545A2BEB67D200191286 /* DateFormatterLib.swift in Sources */, 523ED2602BDA2BC700CFED02 /* SceneDelegate.swift in Sources */, 9CBCB2AA2BE51A52007D7934 /* HomeVC.swift in Sources */, 52D774E92BDFBDA4001D87DE /* AuthenticationStringConstant.swift in Sources */, @@ -1294,6 +1308,25 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 5259544F2BEB5EB700191286 /* XCRemoteSwiftPackageReference "SkeletonView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Juanpe/SkeletonView.git"; + requirement = { + kind = exactVersion; + version = 1.31.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 525954502BEB5EB700191286 /* SkeletonView */ = { + isa = XCSwiftPackageProductDependency; + package = 5259544F2BEB5EB700191286 /* XCRemoteSwiftPackageReference "SkeletonView" */; + productName = SkeletonView; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 523ED2522BDA2BC700CFED02 /* Project object */; } diff --git a/WOKA/Authentication/Base.lproj/AuthenticationSB.storyboard b/WOKA/Authentication/Base.lproj/AuthenticationSB.storyboard index e3b9975..165e0f9 100644 --- a/WOKA/Authentication/Base.lproj/AuthenticationSB.storyboard +++ b/WOKA/Authentication/Base.lproj/AuthenticationSB.storyboard @@ -404,7 +404,7 @@ Sent to Your Parent’s Email - + @@ -727,6 +727,7 @@ Sent to Your Parent’s Email + diff --git a/WOKA/Authentication/Controller/EmailVC.swift b/WOKA/Authentication/Controller/EmailVC.swift index da25306..fe6e46d 100644 --- a/WOKA/Authentication/Controller/EmailVC.swift +++ b/WOKA/Authentication/Controller/EmailVC.swift @@ -97,3 +97,21 @@ extension EmailVC : UITextFieldDelegate{ } } + + +extension UITextField{ + func hideError(){ + if let rightView = self.rightView { + // Hide the right view + rightView.isHidden = true + + // Check if the right view is hidden + if rightView.isHidden { + // If hidden, hide the associated error view + if let errorView = errorViews.object(forKey: self) { + errorView.isHidden = true + } + } + } + } +} diff --git a/WOKA/Authentication/Controller/SelectAvatarVC.swift b/WOKA/Authentication/Controller/SelectAvatarVC.swift index f336145..aff458c 100644 --- a/WOKA/Authentication/Controller/SelectAvatarVC.swift +++ b/WOKA/Authentication/Controller/SelectAvatarVC.swift @@ -39,12 +39,12 @@ class SelectAvatarVC: UIViewController { extension SelectAvatarVC : UICollectionViewDelegate , UICollectionViewDataSource{ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 10 + return vm.avatarData.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.CellIdentifier.Authentication.selectAvatarCell, for: indexPath) as! SelectAvatarCell - cell.setData() + cell.setData(data: vm.avatarData[indexPath.row]) return cell } diff --git a/WOKA/Authentication/Controller/UserDetailsRegisterVC.swift b/WOKA/Authentication/Controller/UserDetailsRegisterVC.swift index 648460e..780be0a 100644 --- a/WOKA/Authentication/Controller/UserDetailsRegisterVC.swift +++ b/WOKA/Authentication/Controller/UserDetailsRegisterVC.swift @@ -33,7 +33,7 @@ class UserDetailsRegisterVC : UIViewController{ } // MARK: - Button Tap Handler - + @IBAction func nextBtnTapped(_ sender: LocalisedElementsButton) { guard let name = enterNameTF.text ,let userName = enterUserNameTF.text , let pass = enterPasswordTF.text else{return} @@ -51,7 +51,7 @@ class UserDetailsRegisterVC : UIViewController{ */ if userName.count < 3{ enterUserNameTF.rightView?.isHidden = false - enterUserNameTF.setError("Username is too short.", show: true) + enterUserNameTF.setError(K.ConstantString.shortUsername, show: true) return } @@ -59,21 +59,35 @@ class UserDetailsRegisterVC : UIViewController{ Check for password */ if pass.count < 6{ - enterPasswordTF.rightView?.isHidden = false - enterPasswordTF.setError("Name is too short.", show: true) + let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC + + vcPush.contentLabel = K.ConstantString.shortPass + vcPush.mainTitleText = K.ConstantString.error +// vcPush.onDoneBlock = { isDone in } + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + self.present(vcPush, animated: true) return } /* - Initializing our local data store for user Register + Check if the username exist or not */ - AuthFunc.shareInstance.regData.full_name = name - AuthFunc.shareInstance.regData.username = userName - AuthFunc.shareInstance.regData.password = pass - - let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil) - let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.userIntrestVC) as! UserIntrestVC - self.navigationController?.pushViewController(vc, animated: true) + vm.checkUsernameExist { isDone in + if isDone{ + /* + Initializing our local data store for user Register + */ + AuthFunc.shareInstance.regData.full_name = name + AuthFunc.shareInstance.regData.username = userName + AuthFunc.shareInstance.regData.password = pass + + let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil) + let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.userIntrestVC) as! UserIntrestVC + self.navigationController?.pushViewController(vc, animated: true) + } + } } } @@ -84,9 +98,11 @@ extension UserDetailsRegisterVC : UITextFieldDelegate{ func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{ switch textField{ case enterNameTF: + textField.hideError() if !string.nameCharacterOnly(){return false} return ValidatorClass.sharedInstanec.limitCharacter(length: 50,textField, shouldChangeCharactersIn: range, replacementString: string) case enterUserNameTF: + textField.hideError() if !string.numberAndCharacterAndSpecialChar(){return false} return ValidatorClass.sharedInstanec.limitCharacter(length: 16,textField, shouldChangeCharactersIn: range, replacementString: string) case enterPasswordTF: diff --git a/WOKA/Authentication/Controller/UserIntrestVC.swift b/WOKA/Authentication/Controller/UserIntrestVC.swift index 19ef003..55d2c9a 100644 --- a/WOKA/Authentication/Controller/UserIntrestVC.swift +++ b/WOKA/Authentication/Controller/UserIntrestVC.swift @@ -19,6 +19,7 @@ class UserIntrestVC: UIViewController { @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var nextBtn: LocalisedElementsButton! @IBOutlet weak var scrollView: UIScrollView! + @IBOutlet weak var fullName: UILabel! @IBOutlet weak var contentHeight: NSLayoutConstraint! @@ -58,6 +59,54 @@ class UserIntrestVC: UIViewController { } @IBAction func nextBtnTapped(_ sender: LocalisedElementsButton) { + let dob = DateFormatterLib.dateModsDate(date: datePicker.date, dateReturnFormat: .yyyy_MM_dd, stringOrDate: .string).0 + /* + Append the DOB to RegData + */ + AuthFunc.shareInstance.regData.date_of_birth = dob + + // Check for Gender. + if AuthFunc.shareInstance.regData.gender == nil{ + let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC + + vcPush.contentLabel = K.ConstantString.genderSel + vcPush.mainTitleText = K.ConstantString.error + // vcPush.onDoneBlock = { isDone in } + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + self.present(vcPush, animated: true) + return + } + + // Check for Intrest. + if AuthFunc.shareInstance.regData.interest_topic_id == nil || AuthFunc.shareInstance.regData.interest_topic_id?.count == 0{ + let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC + + vcPush.contentLabel = K.ConstantString.intrest + vcPush.mainTitleText = K.ConstantString.error + // vcPush.onDoneBlock = { isDone in } + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + self.present(vcPush, animated: true) + return + } + + // Check for DOB. + if AuthFunc.shareInstance.regData.date_of_birth == nil{ + let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC + + vcPush.contentLabel = K.ConstantString.dob + vcPush.mainTitleText = K.ConstantString.error + // vcPush.onDoneBlock = { isDone in } + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + self.present(vcPush, animated: true) + return + } + let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil) let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.selectAvatarVC) as! SelectAvatarVC self.navigationController?.pushViewController(vc, animated: true) @@ -80,7 +129,19 @@ extension UserIntrestVC : UICollectionViewDelegate , UICollectionViewDataSource{ func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { vm.intrestTopics[indexPath.row].isSelected?.toggle() - + + //Append remove intrest ID + if let id = vm.intrestTopics[indexPath.row].id{ + if let topicID = AuthFunc.shareInstance.regData.interest_topic_id, let index = topicID.firstIndex(of: id){ + AuthFunc.shareInstance.regData.interest_topic_id?.remove(at: index) + }else{ + if AuthFunc.shareInstance.regData.interest_topic_id == nil { + AuthFunc.shareInstance.regData.interest_topic_id = [] + } + AuthFunc.shareInstance.regData.interest_topic_id?.append(id) + } + } + print(AuthFunc.shareInstance.regData.interest_topic_id) UIView.performWithoutAnimation { self.collectionView.reloadItems(at: [IndexPath(row: indexPath.row, section: 0)]) } @@ -115,3 +176,69 @@ extension UserIntrestVC : UICollectionViewDelegateFlowLayout{ } } + + +extension UIView { + func startShimmeringViewAnimation() { + + let gradientLayer = CAGradientLayer() + gradientLayer.frame = bounds + gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0) + gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0) + let gradientColorOne = #colorLiteral(red: 0.7529411765, green: 0.7529411765, blue: 0.7529411765, alpha: 1).cgColor + let gradientColorTwo = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1).cgColor + gradientLayer.colors = [gradientColorOne, gradientColorTwo, gradientColorOne] + gradientLayer.locations = [0.0, 0.5, 1.0] + layer.addSublayer(gradientLayer) + + startShimmerAnimation(on: gradientLayer) + } + + func stopShimmeringViewAnimation() { + guard let gradientLayer = layer.sublayers?.first(where: { $0 is CAGradientLayer }) else { + return + } + gradientLayer.removeAllAnimations() + gradientLayer.removeFromSuperlayer() + } + + private func startShimmerAnimation(on layer: CALayer) { + let animation = CABasicAnimation(keyPath: "locations") + animation.fromValue = [-1.0, -0.5, 0.0] + animation.toValue = [1.0, 1.5, 2.0] + animation.repeatCount = .infinity + animation.duration = 1.25 + layer.add(animation, forKey: animation.keyPath) + } + +} + + +import UIKit + +class ShimmerView: UIView { + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + var gradientLayer: CAGradientLayer { + return layer as! CAGradientLayer + } + + override func layoutSubviews() { + super.layoutSubviews() + + gradientLayer.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, UIColor.clear.cgColor] + gradientLayer.locations = [0.0, 0.5, 1.0] + gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + + let animation = CABasicAnimation(keyPath: "transform.translation.x") + animation.duration = 1.0 + animation.fromValue = -frame.width + animation.toValue = frame.width + animation.repeatCount = Float.infinity + gradientLayer.add(animation, forKey: "shimmerAnimation") + } +} diff --git a/WOKA/Authentication/Model/AvatarDM.swift b/WOKA/Authentication/Model/AvatarDM.swift new file mode 100644 index 0000000..12f272b --- /dev/null +++ b/WOKA/Authentication/Model/AvatarDM.swift @@ -0,0 +1,32 @@ +// +// AvatarDM.swift +// WOKA +// +// Created by MacBook Pro on 08/05/24. +// + +import Foundation + +// MARK: - AvatarDM +struct AvatarDM: Codable { + let result: [ResultRecords]? + let totalRecords: Int? + + enum CodingKeys: String, CodingKey { + case result + case totalRecords = "total_records" + } + + // MARK: - Result + struct ResultRecords: Codable { + let id: Int? + let avatarName: String? + let avatarImageURL: String? + + enum CodingKeys: String, CodingKey { + case id + case avatarName = "avatar_name" + case avatarImageURL = "avatar_image_url" + } + } +} diff --git a/WOKA/Authentication/Model/UserRegPostModel.swift b/WOKA/Authentication/Model/UserRegPostModel.swift index 04c62f9..78df19f 100644 --- a/WOKA/Authentication/Model/UserRegPostModel.swift +++ b/WOKA/Authentication/Model/UserRegPostModel.swift @@ -7,46 +7,35 @@ import Foundation -//[{"key":"full_name","value":"DemoUser","description":"mandatory","type":"text"},{"key":"username","value":"tests104","description":"mandatory","type":"text"},{"key":"password","value":"123456","description":"mandatory (minimum 6 character)","type":"text"},{"key":"gender","value":"1","description":"mandatory (1 for girl/female, 2 for boy/male)","type":"text"},{"key":"birthdate","value":"2015-11-1","description":"mandatory","type":"text"},{"key":"email","value":"pradyumn@wdimails.com1","description":"mandatory","type":"text"},{"key":"guardian_email","value":"pradyumn@wdimails.com1","description":"mandatroy if user type = 1","type":"text"},{"key":"user_type","value":"1","description":"mandatory ( 1 = below 16, 2 = above 16)","type":"text"},{"key":"language_id","value":"1","description":"mandatory","type":"text"},{"key":"ip_address","value":"111","description":"non mandatory","type":"text","enabled":false},{"key":"interest_topic_id[0]","value":"1","description":"mandatory if user type=1","type":"text"},{"key":"interest_topic_id[1]","value":"2","description":"mandatory if user type=1","type":"text"},{"key":"avtar","value":"avatar1.png","description":"mandatory","type":"text"},{"key":"add_child","value":"1","description":"mandatory when parent adding child","type":"text"}] - struct UserRegPostModel: Encodable { var full_name: String? var username : String? var password : String? - var date_of_birth: String? - var contact_number: String? + var gender : Int? //mandatory (1 for girl/female, 2 for boy/male) + var date_of_birth: String? //2015-11-1 var email: String? - var street: String? - var town: String? - var country: String? - var state: String? - var zip_code: String? - var lat: String? - var lng: String? - var pin_code: String? - var cpin_code: String? - var one_signal_player_id: String? - var timezone: String? + var guardian_email: String? + var user_type: String? + var language_id: String? + var interest_topic_id: [Int]? + var avtar: String? + var add_child: String? + var dictionaryRepresentation: [String: Any] { return [ "full_name": full_name ?? "", "username" : username ?? "", "password" : password ?? "", + "gender" : gender ?? "", "date_of_birth": date_of_birth ?? "", - "contact_number": contact_number ?? "", "email": email ?? "", - "street": street ?? "", - "town": town ?? "", - "country": country ?? "", - "state": state ?? "", - "zip_code": zip_code ?? "", - "lat": lat ?? "", - "lng": lng ?? "", - "pin_code": pin_code ?? "", - "cpin_code": cpin_code ?? "", - "one_signal_player_id": one_signal_player_id ?? "", - "timezone": timezone ?? "" + "guardian_email": guardian_email ?? "", + "user_type": user_type ?? "", + "language_id": language_id ?? "", + "interest_topic_id": interest_topic_id ?? [], + "avtar": avtar ?? "", + "add_child": add_child ?? "", ] } } diff --git a/WOKA/Authentication/View/SelectAvatarCell.swift b/WOKA/Authentication/View/SelectAvatarCell.swift index 882d074..c7c340e 100644 --- a/WOKA/Authentication/View/SelectAvatarCell.swift +++ b/WOKA/Authentication/View/SelectAvatarCell.swift @@ -21,7 +21,10 @@ class SelectAvatarCell: UICollectionViewCell { self.roundCorner() } - func setData(){ + func setData(data : AvatarDM.ResultRecords){ + if let url = data.avatarImageURL{ + self.imageView.imageURL(url) + } // self.imageView.image = UIImage(named: "avatar") } } diff --git a/WOKA/Authentication/View/YourIntrestCell.swift b/WOKA/Authentication/View/YourIntrestCell.swift index d3b997a..7c76a2e 100644 --- a/WOKA/Authentication/View/YourIntrestCell.swift +++ b/WOKA/Authentication/View/YourIntrestCell.swift @@ -8,17 +8,18 @@ import UIKit class YourIntrestCell: UICollectionViewCell { - + @IBOutlet weak var outerView: UIView! @IBOutlet weak var intrestLabel: UILabel! override func awakeFromNib() { super.awakeFromNib() + } override func layoutSubviews() { outerView.roundCorner(radius: 20) -// outerView.backgroundColor = UIColor.white.withAlphaComponent(0.5) + // outerView.backgroundColor = UIColor.white.withAlphaComponent(0.5) } func setData(data : IntrestTopicDM.Result){ @@ -30,5 +31,4 @@ class YourIntrestCell: UICollectionViewCell { outerView.backgroundColor = UIColor.white.withAlphaComponent(0.5) } } - } diff --git a/WOKA/Authentication/ViewModel/SelectAvatarVM.swift b/WOKA/Authentication/ViewModel/SelectAvatarVM.swift index e644370..117dad0 100644 --- a/WOKA/Authentication/ViewModel/SelectAvatarVM.swift +++ b/WOKA/Authentication/ViewModel/SelectAvatarVM.swift @@ -10,13 +10,14 @@ import UIKit class SelectAvatarVM{ weak var vc : SelectAvatarVC! - + var avatarData = [AvatarDM.ResultRecords]() func initView(){ let color1 = #colorLiteral(red: 0.144693464, green: 0.1426281333, blue: 0.6686832905, alpha: 1) let color2 = #colorLiteral(red: 0.6901960784, green: 0.2745098039, blue: 0.7568627451, alpha: 1) vc.nextBtn.applyGradient(colors: [color1, color2], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0.8, y: 0)) vc.nextBtn.roundCorner() setupCell() + getAvatarListing() } func setupCell(){ @@ -24,4 +25,31 @@ class SelectAvatarVM{ vc.collectionView.delegate = self.vc vc.collectionView.dataSource = self.vc } + + // MARK: - Get Intrests + + func getAvatarListing(){ + Utilities.startProgressHUD() + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Auth.avatar_listing, method: .get) {(result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + switch data.success{ + case 0: + Utilities.dismissProgressHUD() + self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + case 1: + Utilities.dismissProgressHUD() + if let avatarData = data.data?.result{ + self.avatarData = avatarData + self.vc.collectionView.reloadData() + } + default: + break + } + case .failure(let error): + Utilities.dismissProgressHUD() + self.vc.toast(msg: error.localizedDescription, time: 2) + } + } + } } diff --git a/WOKA/Authentication/ViewModel/UserDetailsRegisterVM.swift b/WOKA/Authentication/ViewModel/UserDetailsRegisterVM.swift index 75e08fb..4d335d7 100644 --- a/WOKA/Authentication/ViewModel/UserDetailsRegisterVM.swift +++ b/WOKA/Authentication/ViewModel/UserDetailsRegisterVM.swift @@ -6,6 +6,7 @@ // import UIKit +import Alamofire class UserDetailsRegisterVM{ @@ -30,7 +31,7 @@ class UserDetailsRegisterVM{ //Adding error view to the name tf vc.enterNameTF.addRightButton(title: "", tintColor: UIColor.red, btnImage: UIImage(systemName: "exclamationmark.circle.fill"), target: self, action: #selector(errorName)) vc.enterNameTF.rightView?.isHidden = true - vc.enterUserNameTF.addRightButton(title: "", tintColor: UIColor.red, btnImage: UIImage(systemName: "exclamationmark.circle.fill"), target: self, action: #selector(errorName)) + vc.enterUserNameTF.addRightButton(title: "", tintColor: UIColor.red, btnImage: UIImage(systemName: "exclamationmark.circle.fill"), target: self, action: #selector(errorUserName)) vc.enterUserNameTF.rightView?.isHidden = true } @@ -42,7 +43,7 @@ class UserDetailsRegisterVM{ } @objc func errorUserName(){ - let errorView = errorViews.object(forKey: vc.enterNameTF) + let errorView = errorViews.object(forKey: vc.enterUserNameTF) if let errorView = errorView { errorView.isHidden.toggle() } @@ -60,4 +61,37 @@ class UserDetailsRegisterVM{ i.delegate = vc.self } } + + // MARK: - Get Intrests + + func checkUsernameExist(onCompletion: @escaping (Bool) -> Void){ + let params: Parameters = [ + "email": AuthFunc.shareInstance.regData.email!, + "username": vc.enterUserNameTF.text!, + "user_type": AuthFunc.shareInstance.userType == .adult ? "2" :"1" + ] + + Utilities.startProgressHUD(msg: K.ConstantString.userNameVerify) + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Auth.check_exist_username, method: .post,parameters: params) {(result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + //0 -> Username already used. , 1-> Username available + switch data.success{ + case 0: + Utilities.dismissProgressHUD() + self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + onCompletion(false) + case 1: + Utilities.dismissProgressHUD() + onCompletion(true) + default: + break + } + case .failure(let error): + Utilities.dismissProgressHUD() + self.vc.toast(msg: error.localizedDescription, time: 2) + onCompletion(false) + } + } + } } diff --git a/WOKA/Authentication/ViewModel/UserIntrestVM.swift b/WOKA/Authentication/ViewModel/UserIntrestVM.swift index a0c1792..3854ee1 100644 --- a/WOKA/Authentication/ViewModel/UserIntrestVM.swift +++ b/WOKA/Authentication/ViewModel/UserIntrestVM.swift @@ -11,14 +11,26 @@ import Alamofire class UserIntrestVM{ weak var vc : UserIntrestVC! - var gender = GenderEnum.none +// var gender = GenderEnum.none var intrestTopics = [IntrestTopicDM.Result]() func initView(){ setupCell() - let bottomPadding: CGFloat = 60 // Adjust this value as needed + /* + Setting the minimum and maximum date as per user type + */ + if AuthFunc.shareInstance.userType == .adult{ + vc.datePicker.minimumDate = Calendar.current.date(byAdding: .year, value: -150, to: Date()) + vc.datePicker.maximumDate = Calendar.current.date(byAdding: .year, value: -16, to: Date()) + }else{ + vc.datePicker.minimumDate = Calendar.current.date(byAdding: .year, value: -16, to: Date()) + vc.datePicker.maximumDate = Calendar.current.date(byAdding: .year, value: -3, to: Date()) + } + + vc.fullName.text = (AuthFunc.shareInstance.regData.full_name != nil && AuthFunc.shareInstance.regData.full_name != "") ? AuthFunc.shareInstance.regData.full_name : "Guardian" + let bottomPadding: CGFloat = 60 // Adjust this value as needed // Get the current content inset var contentInset = vc.scrollView.contentInset @@ -48,14 +60,14 @@ class UserIntrestVM{ func setGender(){ let alphaComp = 0.6 - switch gender{ - case .boy: + switch AuthFunc.shareInstance.regData.gender{ + case 2: vc.boyView.backgroundColor = UIColor.white vc.girlView.backgroundColor = UIColor.white.withAlphaComponent(alphaComp) - case .girl: + case 1: vc.girlView.backgroundColor = UIColor.white vc.boyView.backgroundColor = UIColor.white.withAlphaComponent(alphaComp) - case .none: + default: vc.girlView.backgroundColor = UIColor.white.withAlphaComponent(alphaComp) vc.boyView.backgroundColor = UIColor.white.withAlphaComponent(alphaComp) } @@ -63,7 +75,7 @@ class UserIntrestVM{ @objc func boyBtnTapped() { // Apply click effect animation - gender = .boy + AuthFunc.shareInstance.regData.gender = 2 UIView.animate(withDuration: 0.1, animations: { self.vc.boyView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) }) { _ in @@ -75,7 +87,8 @@ class UserIntrestVM{ } @objc func girlBtnTapped() { - gender = .girl + AuthFunc.shareInstance.regData.gender = 1 + // Apply click effect animation UIView.animate(withDuration: 0.1, animations: { self.vc.girlView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) @@ -118,7 +131,7 @@ class UserIntrestVM{ self.vc.view.layoutIfNeeded() } - self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) +// self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) default: break } diff --git a/WOKA/Constants K/ConstantString.swift b/WOKA/Constants K/ConstantString.swift index 0111d50..fd7219f 100644 --- a/WOKA/Constants K/ConstantString.swift +++ b/WOKA/Constants K/ConstantString.swift @@ -19,5 +19,14 @@ extension K{ static let noInternet = "Make sure you are connected to the internet!" static let minAge = "Minimum age requirement is 18 or above" + + static let genderSel = "Please select Gender." + static let shortPass = "Password is too short." + static let shortUsername = "Username is too short." + static let userNameVerify = "Verifying Username" + static let intrest = "Please select intrest." + static let dob = "Please select DOB." + + static let error = "Error" } } diff --git a/WOKA/Helpers/DateFormatterLib.swift b/WOKA/Helpers/DateFormatterLib.swift new file mode 100644 index 0000000..9d17ba9 --- /dev/null +++ b/WOKA/Helpers/DateFormatterLib.swift @@ -0,0 +1,298 @@ +// +// DateFormatterLib.swift +// WOKA +// +// Created by MacBook Pro on 08/05/24. +// + +import UIKit + +class DateFormatterLib{ + + static func getMinutesDifferenceFromTwoDates(start: Date, end: Date) -> Int{ + + let diff = Int(end.timeIntervalSince1970 - start.timeIntervalSince1970) + let hours = diff / 3600 + let minutes = (diff - hours * 3600) / 60 + return minutes + } + + static func convertToDate(dateFormat : DateFormats , dateStr : String) -> Date { + + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = dateFormat.rawValue + let date = dateFormatter.date(from:dateStr)! + return date + } + + static func dateConvert (date : String) -> String?{ // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM + let isoDate = date + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + let date = dateFormatter.date(from:isoDate)! + dateFormatter.dateFormat = "d-MMMM-yyyy h:mm a" + let resultString = dateFormatter.string(from: date) + return resultString + } + + static func getDate(date : String) -> String?{ // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM + let isoDate = date + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + let date = dateFormatter.date(from:isoDate)! + dateFormatter.dateFormat = "d-MMMM-yyyy" + let resultString = dateFormatter.string(from: date) + return resultString + } + + static func getTime(date : String) -> String?{ // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM + let isoDate = date + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + let date = dateFormatter.date(from:isoDate)! + dateFormatter.dateFormat = "h:mm a" + let resultString = dateFormatter.string(from: date) + return resultString + } + + static func time(date : Date)-> String{ + let formatter = DateFormatter() + formatter.dateFormat = "h:mm a" + let currentTime = formatter.string(from: date) + return currentTime + } + + static func date(date : Date)-> String{ + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd" + let currentTime = formatter.string(from: date) + return currentTime + } + + static func timeFormat(dateStr : String) -> String?{ // am pm to 24 hour + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "hh:mm a" + let item = dateStr + let date = dateFormatter.date(from: item)! + dateFormatter.dateFormat = "HH:mm" + let currentTime = dateFormatter.string(from: date) + return currentTime + } + + static func addMinToString(data : String , minToAdd : Double , format : DateFormats) -> (String? , Date?){ + let isoDate = data + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + let dateMod = dateFormatter.date(from:isoDate)! + let minAdded = dateMod.addingTimeInterval(minToAdd * 60) + dateFormatter.dateFormat = format.rawValue + let resultString = dateFormatter.string(from: minAdded) + return (resultString,minAdded) + } + + static func addSecondToString(data : String , secondToAdd : Double , format : DateFormats) -> (String? , Date?){ + let isoDate = data + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + let dateMod = dateFormatter.date(from:isoDate)! + let minAdded = dateMod.addingTimeInterval(secondToAdd) + dateFormatter.dateFormat = format.rawValue + let resultString = dateFormatter.string(from: minAdded) + return (resultString,minAdded) + } + + static func dateMods(dateStr : String,dateCurrentFormat : DateFormats, dateReturnFormat : DateFormats,stringOrDate : StringOrDate) -> (String?,Date?){ + if dateStr == ""{ + return ("",nil) + } + let isoDate = dateStr + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX 1991-11-29 00:00:00 + dateFormatter.dateFormat = dateCurrentFormat.rawValue + let date = dateFormatter.date(from:isoDate)! + dateFormatter.dateFormat = dateReturnFormat.rawValue + + switch stringOrDate { + case .date: + return (nil,date) + case .string: + let resultString = dateFormatter.string(from: date) + return (resultString,nil) + case .both: + let resultString = dateFormatter.string(from: date) + return (resultString,date) + } + } + + static func abbrevationTimeConversion(dateStr : String, dateCurrentFormat : DateFormats, dateReturnFormat : DateFormats, timeZoneAbbrevation : TimeZoneAbbreviation) -> String?{ + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = dateCurrentFormat.rawValue + dateFormatter.timeZone = TimeZone(abbreviation: timeZoneAbbrevation.rawValue) + + if let date = dateFormatter.date(from: dateStr) { + dateFormatter.timeZone = TimeZone.current + dateFormatter.dateFormat = dateReturnFormat.rawValue + + return dateFormatter.string(from: date) + } + return nil + } + + static func dateModsDate(date : Date, dateReturnFormat : DateFormats,stringOrDate : StringOrDate) -> (String?,Date?){ + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = dateReturnFormat.rawValue + dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX 1991-11-29 00:00:00 + + let dateFormatted = dateFormatter.string(from: date) + switch stringOrDate { + case .date: + return (nil,date) + case .string: +// let resultString = dateFormatter.string(from: date) + return (dateFormatted,nil) + case .both: + return (dateFormatted,date) + } + } + + static func convertTimeStringToCurrentDate(time : String, format : DateFormats) -> Date?{ + // Step 1: Get the current date + let currentDate = Date() + + // Step 2: Parse the time string + let timeString = time // Replace with your desired time string + let timeFormatter = DateFormatter() + timeFormatter.timeZone = TimeZone.current // Use the current time zone + timeFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX 1991-11-29 00:00:00 + + timeFormatter.dateFormat = format.rawValue + if let time = timeFormatter.date(from: timeString) { + // Step 3: Combine the date and time + let calendar = Calendar.current + let combinedDate = calendar.date(bySettingHour: calendar.component(.hour, from: time), + minute: calendar.component(.minute, from: time), + second: calendar.component(.second, from: time), + of: currentDate) + + if let combinedDate = combinedDate { + // Now, combinedDate contains the current date with the time from the time string + return combinedDate + } else { + return nil + } + } else { + return nil + } + + } +} + +extension Date { + func withAddedMinutes(minutes: Double) -> Date { + addingTimeInterval(minutes * 60) + } + + func withAddedHours(hours: Double) -> Date { + withAddedMinutes(minutes: hours * 60) + } + + static func -(lhs: Date, rhs: Int) -> Date { + return Calendar.current.date(byAdding: .day, value: -rhs, to: lhs)! + } +} + +//enum DateFormats: String, CaseIterable { +// case yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss" +// case yyyy_MM_dd_T_HH_mm_ss_SSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" +// case HH_mm = "HH:mm" +// case yyyy_MM_dd = "yyyy-MM-dd" +// case HH_mm_ss = "HH:mm:ss" +// case yyyy_MM_dd_HH_mm_ss_Z = "yyyy-MM-dd HH:mm:ss Z" //2023-02-28 03:00:29 +0000 +// case dd_MM_yyyy = "dd-MM-yyyy" // 26-06-1991 +//} + +enum StringOrDate { + case date + case string + case both +} + +enum DateFormats: String, CaseIterable { + case d = "d" // 2 + case EEEE = "EEEE" // wednesday + case EEE = "EEE" // wed + + case yyyy_MM_dd_T_HH_mm_ss_SSSZ = "yyyy_MM_dd_T_HH_mm_ss_SSSZ" + + case yyyy_MM_ddTHH_mm_ss_ssZ = "yyyy-MM-dd'T'HH:mm:ss:ssZ" // + + case yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss" // 2023-07-25 14:03:07 + + case yyyy_MM_dd = "yyyy-MM-dd" + case MMMM_d_yyyy_h_mm_a = "MMMM d, yyyy, h:mm a" // December 6, 2022, 3:55 PM + + + case d_MMM_yyyy_at_h_mm_a = "d MMM yyyy 'at' h:mm a" // 27 Jan 2023 at 4:30 pm + + case d_MMMM_yyyy_h_mm_a = "d MMMM yyyy, h:mm a" //2 Dec 2022, 12:34 PM + + case dd_MM_yyyy = "dd-MM-yyyy" // 26-06-1991 + + case MM_dd_yyyy = "MM-dd-yyyy" // 06-26-1991 + + case h_mm_a_d_MMM_yyyy = "h:mm a, d MMM yyyy" // 2:45 pm, 22 Sep 2022 + + case h_mm_a_MMM_d_yyyy = "h:mm a, MMM d yyyy" // 11:07 AM, Aug 16 2022 + + case d_MMM_yyyy = "d MMM yyyy" // 28 Nov 2022 + case d_MMMM_yyyy = "d MMMM yyyy" // 28 November 2022 + case d_MMM__yyyy = "d MMM, yyyy" // 28 Nov, 2022 + case MMM_d_yyyy = "MMM d, yyyy" // Nov 28, 2022 + case MMMM_d = "MMMM, d" // March 16 + + // Times + case HH_mm = "HH:mm" + case HH_mm_ss = "HH:mm:ss" + case h_mm_a = "h:mm a" + case h_a = "hh a" + case h_mm_ss_a = "h:mm:ss a" + case d_MM = "d MMM" // 12 Oct + case h__mm__a = "h : mm a" +} + +// List of abbrevation for different zones +enum TimeZoneAbbreviation: String { + case UTC = "UTC" + case GMT = "GMT" + case EST = "EST" + case CST = "CST" + case MST = "MST" + case PST = "PST" + case AST = "AST" + case AKST = "AKST" + case HST = "HST" + case AEDT = "AEDT" + case AEST = "AEST" + case ACDT = "ACDT" + case ACST = "ACST" + case AWST = "AWST" + case JST = "JST" + case KST = "KST" + case IST = "IST" + case CET = "CET" + case CEST = "CEST" + case EET = "EET" + case MSK = "MSK" + case NZST = "NZST" + case NST = "NST" + + // Example usage: +// let timeZone: TimeZoneAbbreviation = .EST +// print("Time Zone Abbreviation: \(timeZone.rawValue)") +} diff --git a/WOKA/Helpers/LoadingIndicatorImageView.swift b/WOKA/Helpers/LoadingIndicatorImageView.swift new file mode 100644 index 0000000..8e563dd --- /dev/null +++ b/WOKA/Helpers/LoadingIndicatorImageView.swift @@ -0,0 +1,36 @@ +// +// LoadingIndicatorImageView.swift +// WOKA +// +// Created by MacBook Pro on 08/05/24. +// + +import UIKit +import SDWebImage + +extension UIImageView { + + func imageURL(_ url: String, color : UIColor = UIColor.black) { + let activityIndicator = UIActivityIndicatorView(style: .medium) + activityIndicator.tintColor = UIColor.darkGray + activityIndicator.color = color + activityIndicator.frame = CGRect(x: 0, y: 0, width: 64, height: 64) + activityIndicator.hidesWhenStopped = true + activityIndicator.startAnimating() + activityIndicator.translatesAutoresizingMaskIntoConstraints = true + + // activityIndicator.center = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2) + activityIndicator.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) + + // bottom is for resizing the indicator to be perfect in center + activityIndicator.autoresizingMask = (UIView.AutoresizingMask(rawValue: UIView.AutoresizingMask.RawValue(UInt8(UIView.AutoresizingMask.flexibleRightMargin.rawValue) | UInt8(UIView.AutoresizingMask.flexibleLeftMargin.rawValue) | UInt8(UIView.AutoresizingMask.flexibleBottomMargin.rawValue) | UInt8(UIView.AutoresizingMask.flexibleTopMargin.rawValue)))) + + self.addSubview(activityIndicator) + // Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false) { _ in + self.sd_setImage(with: URL(string: url.replacingOccurrences(of: " ", with: "%20"))) { (image, error, cacheType, url) in + activityIndicator.stopAnimating() + } + // } + } + +} diff --git a/WOKA/Network Adapter/APIEndPoints.swift b/WOKA/Network Adapter/APIEndPoints.swift index 464565a..f47f9d4 100644 --- a/WOKA/Network Adapter/APIEndPoints.swift +++ b/WOKA/Network Adapter/APIEndPoints.swift @@ -27,6 +27,8 @@ struct APIEndPoints { static let user_email_verification = makeURL(path: "user_email_verification") static let validate_otp = makeURL(path: "validate_otp") static let interest_topic_listing = makeURL(path: "interest_topic_listing") + static let check_exist_username = makeURL(path: "check_exist_username") + static let avatar_listing = makeURL(path: "avatar_listing") } // Other endpoint categories...