- Removed the pod for center collection view. Now instead of library i have created a custom flowlayout

- Added the Forgot password otp send api.
- Done the error handling and navigation for the same.
- Added api for password updated.
- Added necessary Checks for the password.
- Fixed the versioning issue of the centered flow layout. Also fixed the errors, for the complex calculations , splitted the calculations to avoid crash.
This commit is contained in:
Bilal
2024-05-10 20:43:57 +05:30
parent 3f2899b9a3
commit ecfa31b57f
14 changed files with 451 additions and 76 deletions

View File

@@ -8,14 +8,13 @@ target 'WOKA' do
pod 'IQKeyboardManagerSwift', '~> 7.0.2'
# GIF Animations
pod 'lottie-ios'
pod 'lottie-ios', '~> 4.4.1'
#Network call
pod 'Alamofire'
pod 'Alamofire' , '~> 5.9.1'
pod 'CollectionViewCenteredFlowLayout'
pod 'SDWebImage'
# Image Loading & Caching
pod 'SDWebImage', '~> 5.19.1'
# Bottom line is for removing IPHONEOS_DEPLOYMENT_TARGET
post_install do |installer|

View File

@@ -90,6 +90,9 @@
52D774F12BDFC53B001D87DE /* StringSubScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D774F02BDFC53B001D87DE /* StringSubScript.swift */; };
52FB2D8F2BDF898F0009B0C7 /* TextFieldPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52FB2D8E2BDF898F0009B0C7 /* TextFieldPadding.swift */; };
619A5A1BD8BD968ADC83C106 /* Pods_WOKA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBA543A4216400A2864E3D3E /* Pods_WOKA.framework */; };
9C0A853F2BEE35340093783D /* ForgotPassDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0A853E2BEE35340093783D /* ForgotPassDM.swift */; };
9C0A85412BEE35670093783D /* ResetPassUserNameVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0A85402BEE35670093783D /* ResetPassUserNameVM.swift */; };
9C0A85432BEE3EC90093783D /* NewPasswordVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0A85422BEE3EC90093783D /* NewPasswordVM.swift */; };
9C27E1602BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E15F2BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift */; };
9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */; };
9C27E1652BDB6FBC00EC1DA9 /* StoryBoardID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E1642BDB6FBC00EC1DA9 /* StoryBoardID.swift */; };
@@ -104,6 +107,7 @@
9C56E8462BDBEE6400E4CA14 /* EmailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56E8452BDBEE6400E4CA14 /* EmailVC.swift */; };
9C56E8482BDBEFAB00E4CA14 /* AssetColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56E8472BDBEFAB00E4CA14 /* AssetColor.swift */; };
9C56E84B2BDBF03F00E4CA14 /* AuthenticationSB.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E84A2BDBF03F00E4CA14 /* AuthenticationSB.storyboard */; };
9C9BEEC72BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */; };
9CBCB29B2BE4D614007D7934 /* LoginVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBCB29A2BE4D614007D7934 /* LoginVC.swift */; };
9CBCB29D2BE4D6BB007D7934 /* LoginVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBCB29C2BE4D6BB007D7934 /* LoginVM.swift */; };
9CBCB29F2BE4E13A007D7934 /* ValidatorClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBCB29E2BE4E13A007D7934 /* ValidatorClass.swift */; };
@@ -218,6 +222,9 @@
52E7E0F62BDF7DD500C86E10 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AuthenticationSB.strings; sourceTree = "<group>"; };
52E7E0F82BDF7DD900C86E10 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/AuthenticationSB.strings; sourceTree = "<group>"; };
52FB2D8E2BDF898F0009B0C7 /* TextFieldPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldPadding.swift; sourceTree = "<group>"; };
9C0A853E2BEE35340093783D /* ForgotPassDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForgotPassDM.swift; sourceTree = "<group>"; };
9C0A85402BEE35670093783D /* ResetPassUserNameVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetPassUserNameVM.swift; sourceTree = "<group>"; };
9C0A85422BEE3EC90093783D /* NewPasswordVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPasswordVM.swift; sourceTree = "<group>"; };
9C27E15F2BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsStruct.swift; sourceTree = "<group>"; };
9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthFunc.swift; sourceTree = "<group>"; };
9C27E1642BDB6FBC00EC1DA9 /* StoryBoardID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryBoardID.swift; sourceTree = "<group>"; };
@@ -238,6 +245,7 @@
9C56E8452BDBEE6400E4CA14 /* EmailVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailVC.swift; sourceTree = "<group>"; };
9C56E8472BDBEFAB00E4CA14 /* AssetColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetColor.swift; sourceTree = "<group>"; };
9C56E8492BDBF03F00E4CA14 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/AuthenticationSB.storyboard; sourceTree = "<group>"; };
9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCenteredFlowLayout.swift; sourceTree = "<group>"; };
9CBCB29A2BE4D614007D7934 /* LoginVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginVC.swift; sourceTree = "<group>"; };
9CBCB29C2BE4D6BB007D7934 /* LoginVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginVM.swift; sourceTree = "<group>"; };
9CBCB29E2BE4E13A007D7934 /* ValidatorClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorClass.swift; sourceTree = "<group>"; };
@@ -344,6 +352,7 @@
52C8B0552BDA57CE003B51D0 /* Constants K */,
52C8B0512BDA4B51003B51D0 /* Helpers */,
523ED2932BDA3D0100CFED02 /* Assets */,
9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */,
523ED2682BDA2BC900CFED02 /* LaunchScreen.storyboard */,
523ED26B2BDA2BC900CFED02 /* Info.plist */,
5259541E2BE8E93500191286 /* Config.xcconfig */,
@@ -599,6 +608,7 @@
525954332BEA620800191286 /* IntrestTopicDM.swift */,
5259545B2BEBB80400191286 /* AvatarDM.swift */,
52A3F6A42BECBA8D0000BB0B /* LinkedChildDM.swift */,
9C0A853E2BEE35340093783D /* ForgotPassDM.swift */,
);
path = Model;
sourceTree = "<group>";
@@ -626,6 +636,8 @@
52C6E0282BE3B52500E22D59 /* SelectAvatarVM.swift */,
9CBCB29C2BE4D6BB007D7934 /* LoginVM.swift */,
52A3F6AE2BECC0690000BB0B /* LinkedChildVM.swift */,
9C0A85402BEE35670093783D /* ResetPassUserNameVM.swift */,
9C0A85422BEE3EC90093783D /* NewPasswordVM.swift */,
);
path = ViewModel;
sourceTree = "<group>";
@@ -889,6 +901,7 @@
52D774EB2BDFC0BF001D87DE /* OTPVC.swift in Sources */,
9C27E16F2BDB866500EC1DA9 /* CellIdentifier.swift in Sources */,
9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */,
9C0A85412BEE35670093783D /* ResetPassUserNameVM.swift in Sources */,
52C6E0292BE3B52500E22D59 /* SelectAvatarVM.swift in Sources */,
52C8B0592BDA57FA003B51D0 /* StaticFilesString.swift in Sources */,
52C8B05D2BDA5AA7003B51D0 /* ApplyGradrient.swift in Sources */,
@@ -909,6 +922,7 @@
525954212BE8EB7900191286 /* APIEndPoints.swift in Sources */,
5259545A2BEB67D200191286 /* DateFormatterLib.swift in Sources */,
523ED2602BDA2BC700CFED02 /* SceneDelegate.swift in Sources */,
9C0A853F2BEE35340093783D /* ForgotPassDM.swift in Sources */,
9CBCB2AA2BE51A52007D7934 /* HomeVC.swift in Sources */,
52D774E92BDFBDA4001D87DE /* AuthenticationStringConstant.swift in Sources */,
5259541B2BE8D6F900191286 /* NetworkReachibility.swift in Sources */,
@@ -925,6 +939,8 @@
525953CF2BE8B28F00191286 /* Utilities.swift in Sources */,
9CBCB2A12BE4E50A007D7934 /* TextFieldPassword.swift in Sources */,
9C56E8482BDBEFAB00E4CA14 /* AssetColor.swift in Sources */,
9C0A85432BEE3EC90093783D /* NewPasswordVM.swift in Sources */,
9C9BEEC72BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift in Sources */,
9CBCB29D2BE4D6BB007D7934 /* LoginVM.swift in Sources */,
5272FCE52BDFDC8C000ECB1D /* UserDetailsRegisterVM.swift in Sources */,
525954272BE9178F00191286 /* UserDataDM.swift in Sources */,
@@ -1156,12 +1172,14 @@
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = WOKA/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = WOKA;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -1192,12 +1210,14 @@
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = WOKA/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = WOKA;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",

View File

@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="VqU-ZQ-5I8">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
@@ -15,25 +14,10 @@
</array>
</customFonts>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-89" y="4"/>
</scene>
<!--Alert CustomVC-->
<scene sceneID="G8M-G5-a7A">
<objects>
<viewController storyboardIdentifier="AlertCustomVC" id="VqU-ZQ-5I8" customClass="AlertCustomVC" customModule="SimpliTend" customModuleProvider="target" sceneMemberID="viewController">
<viewController storyboardIdentifier="AlertCustomVC" id="VqU-ZQ-5I8" customClass="AlertCustomVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="4Fm-io-xfY">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@@ -141,8 +125,5 @@
<namedColor name="WelcomeBlue">
<color red="0.32899999618530273" green="0.32400000095367432" blue="0.4779999852180481" alpha="0.33000001311302185" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@@ -660,7 +660,7 @@ Sent to Your Parents Email</string>
<constraints>
<constraint firstAttribute="height" constant="180" id="auZ-NR-TCk"/>
</constraints>
<collectionViewLayout key="collectionViewLayout" id="Eai-Cb-Sfn" customClass="CollectionViewCenteredFlowLayout" customModule="CollectionViewCenteredFlowLayout"/>
<collectionViewLayout key="collectionViewLayout" id="Eai-Cb-Sfn" customClass="CollectionViewCenteredFlowLayout" customModule="WOKA" customModuleProvider="target"/>
<cells/>
</collectionView>
</subviews>
@@ -1420,40 +1420,40 @@ Sent to Your Parents Email</string>
<size key="intrinsicContentSize" width="8.5" height="23.5"/>
</designable>
<designable name="4gw-z0-s4a">
<size key="intrinsicContentSize" width="200.5" height="20"/>
<size key="intrinsicContentSize" width="150.5" height="20"/>
</designable>
<designable name="68c-1b-KSI">
<size key="intrinsicContentSize" width="201.5" height="21"/>
<size key="intrinsicContentSize" width="151.5" height="21"/>
</designable>
<designable name="81S-Fa-CiD">
<size key="intrinsicContentSize" width="8.5" height="23.5"/>
</designable>
<designable name="DSB-Ge-wNO">
<size key="intrinsicContentSize" width="210" height="21"/>
<size key="intrinsicContentSize" width="160" height="21"/>
</designable>
<designable name="Hcd-Mm-IxW">
<size key="intrinsicContentSize" width="8.5" height="23.5"/>
</designable>
<designable name="JRR-Bk-5UP">
<size key="intrinsicContentSize" width="218" height="20"/>
<size key="intrinsicContentSize" width="168" height="20"/>
</designable>
<designable name="MpT-bm-drv">
<size key="intrinsicContentSize" width="8.5" height="23.5"/>
</designable>
<designable name="Skx-Ig-91N">
<size key="intrinsicContentSize" width="199" height="20"/>
<size key="intrinsicContentSize" width="149" height="20"/>
</designable>
<designable name="iJE-dm-qal">
<size key="intrinsicContentSize" width="200.5" height="20"/>
<size key="intrinsicContentSize" width="150.5" height="20"/>
</designable>
<designable name="m50-FZ-yVO">
<size key="intrinsicContentSize" width="201.5" height="21"/>
<size key="intrinsicContentSize" width="151.5" height="21"/>
</designable>
<designable name="tgW-LH-XfR">
<size key="intrinsicContentSize" width="169.5" height="21"/>
<size key="intrinsicContentSize" width="119.5" height="21"/>
</designable>
<designable name="wy2-0C-rxG">
<size key="intrinsicContentSize" width="201.5" height="21"/>
<size key="intrinsicContentSize" width="151.5" height="21"/>
</designable>
</designables>
<resources>

View File

@@ -18,6 +18,8 @@ class LoginVC: UIViewController {
var vm = LoginVM()
// MARK: - View LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
vm.vc = self

View File

@@ -13,25 +13,62 @@ class NewPasswordVC: UIViewController {
@IBOutlet weak var confirmPassTF: TextFieldShadow!
@IBOutlet weak var nextBtn: LocalisedElementsButton!
var vm = NewPasswordVM()
// MARK: - View LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
initView()
enterNewPasswordTF.enablePasswordToggle()
confirmPassTF.enablePasswordToggle()
enterNewPasswordTF.delegate = self
confirmPassTF.delegate = self
vm.vc = self
vm.initView()
}
func initView(){
enterNewPasswordTF.roundCorner()
confirmPassTF.roundCorner()
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)
nextBtn.applyGradient(colors: [color1, color2], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0.8, y: 0))
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
}
@IBAction func nextBtnTapped(_ sender: LocalisedElementsButton) {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
}
@IBAction func nextBtnTapped(_ sender: LocalisedElementsButton) {
guard let pass = enterNewPasswordTF.text , let confirmPass = confirmPassTF.text else{return}
/*
Check for password
*/
if pass.count < 6 || confirmPass.count < 6{
let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC
vcPush.contentLabel = "Password is too short."
vcPush.mainTitleText = "Error"
// vcPush.onDoneBlock = { isDone in }
vcPush.modalPresentationStyle = .overCurrentContext
vcPush.modalTransitionStyle = .crossDissolve
self.present(vcPush, animated: true)
return
}
/*
Check if password are matching
*/
if pass != confirmPass{
let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.alertCustomVC) as! AlertCustomVC
vcPush.contentLabel = "Password doesn't match"
vcPush.mainTitleText = "Error"
// vcPush.onDoneBlock = { isDone in }
vcPush.modalPresentationStyle = .overCurrentContext
vcPush.modalTransitionStyle = .crossDissolve
self.present(vcPush, animated: true)
return
}
vm.updatePassword()
}
}

View File

@@ -11,17 +11,14 @@ class ResetPassUserNameVC: UIViewController {
@IBOutlet weak var usernameTF: TextFieldShadow!
@IBOutlet weak var nextBtn: LocalisedElementsButton!
var vm = ResetPassUserNameVM()
// MARK: - View LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
initView()
}
func initView(){
usernameTF.roundCorner()
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)
nextBtn.applyGradient(colors: [color1, color2], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0.8, y: 0))
vm.vc = self
vm.initView()
}
override func viewWillAppear(_ animated: Bool) {
@@ -36,9 +33,43 @@ class ResetPassUserNameVC: UIViewController {
@IBAction func nextBtnTapped(_ sender: LocalisedElementsButton) {
let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.oTPVC) as! OTPVC
vc.navigateCheck = .newPass
self.navigationController?.pushViewController(vc, animated: true)
/*
Check for username
*/
if usernameTF.text!.count < 3{
usernameTF.rightView?.isHidden = false
usernameTF.setError(K.ConstantString.shortUsername, show: true)
return
}
vm.sendOtpToUserName()
}
}
// MARK: - Textfield Delegate
extension ResetPassUserNameVC : UITextFieldDelegate{
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
switch textField{
case usernameTF:
textField.hideError()
if !string.numberAndCharacterAndSpecialChar(){return false}
return ValidatorClass.sharedInstanec.limitCharacter(length: 16,textField, shouldChangeCharactersIn: range, replacementString: string)
default:
return true
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField{
case usernameTF:
textField.resignFirstResponder()
default:
break
}
return true
}
}

View File

@@ -0,0 +1,14 @@
//
// ForgotPassDM.swift
// WOKA
//
// Created by Bilal on 10/05/2024.
//
import Foundation
// MARK: - ForgotPassDM
struct ForgotPassDM: Codable {
let email: String?
}

View File

@@ -0,0 +1,61 @@
//
// NewPasswordVM.swift
// WOKA
//
// Created by Bilal on 10/05/2024.
//
import UIKit
import Alamofire
class NewPasswordVM{
weak var vc : NewPasswordVC!
var userName : String?
func initView(){
vc.enterNewPasswordTF.enablePasswordToggle()
vc.confirmPassTF.enablePasswordToggle()
vc.enterNewPasswordTF.delegate = self.vc
vc.confirmPassTF.delegate = self.vc
vc.enterNewPasswordTF.roundCorner()
vc.confirmPassTF.roundCorner()
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()
}
func updatePassword(){
guard let userName else{return}
let params: Parameters = [
"username": userName,
"password": vc.enterNewPasswordTF.text!,
"password_confirmation": vc.confirmPassTF.text!
]
Utilities.startProgressHUD()
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Auth.update_password, method: .post ,parameters: params) {(result : Result<BaseResponseModel<ForgotPassDM>, NetworkManager.APIError>) in
switch result{
case .success(let data):
switch data.success{
case 0: // some error
Utilities.dismissProgressHUD()
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1: // Success
Utilities.dismissProgressHUD()
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 1) {
}
default:
Utilities.dismissProgressHUD()
self.vc.toast(msg: K.ConstantString.unRecognised , time: 1)
}
case .failure(let error):
Utilities.dismissProgressHUD()
self.vc.toast(msg: error.localizedDescription , time: 2)
}
}
}
}

View File

@@ -13,6 +13,9 @@ class OTPVM{
weak var vc : OTPVC!
var validateString = String()
//if user name is not null then the user has forgot the pass.
var userName : String?
var timer: Timer?
var remainingTime: TimeInterval = 10 * 60 // 10 minutes in seconds
@@ -83,8 +86,17 @@ class OTPVM{
return
}
if let userName{
validateForgotPassOTP(otp: otp, userName: userName)
}else{
validateNormalOTP(otp: otp)
}
}
func validateNormalOTP(otp : String){
let params: Parameters = [
"unique_string": validateString,
"unique_string": validateString,
"otp": otp
]
@@ -112,6 +124,39 @@ class OTPVM{
}
}
func validateForgotPassOTP(otp : String, userName : String){
let params: Parameters = [
"username": userName,
"otp": otp
]
Utilities.startProgressHUD()
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Auth.forgot_password_verify_otp, method: .post ,parameters: params) {(result : Result<BaseResponseModel<ForgotPassDM>, NetworkManager.APIError>) in
switch result{
case .success(let data):
switch data.success{
case 0: // some error
Utilities.dismissProgressHUD()
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1: // Success
Utilities.dismissProgressHUD()
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 1) {
let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.newPasswordVC) as! NewPasswordVC
vc.vm.userName = userName
self.vc.navigationController?.pushViewController(vc, animated: true)
}
default:
Utilities.dismissProgressHUD()
self.vc.toast(msg: K.ConstantString.unRecognised , time: 1)
}
case .failure(let error):
Utilities.dismissProgressHUD()
self.vc.toast(msg: error.localizedDescription , time: 2)
}
}
}
func resendOTP(){
let params: Parameters = [
"email": AuthFunc.shareInstance.regData.email!,

View File

@@ -0,0 +1,65 @@
//
// ResetPassUserNameVM.swift
// WOKA
//
// Created by Bilal on 10/05/2024.
//
import UIKit
import Alamofire
class ResetPassUserNameVM{
weak var vc : ResetPassUserNameVC!
func initView(){
vc.usernameTF.roundCorner()
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()
vc.usernameTF.delegate = self.vc
//Adding error view to the name tf
vc.usernameTF.addRightButton(title: "", tintColor: UIColor.red, btnImage: UIImage(systemName: "exclamationmark.circle.fill"), target: self, action: #selector(errorUserName))
vc.usernameTF.rightView?.isHidden = true
}
@objc func errorUserName(){
let errorView = errorViews.object(forKey: vc.usernameTF)
if let errorView = errorView {
errorView.isHidden.toggle()
}
}
// MARK: - Send OTP via username
func sendOtpToUserName(){
let params : Parameters = ["username" : vc.usernameTF.text!]
Utilities.startProgressHUD()
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Auth.forgot_password_send_otp, method: .post, parameters: params) {(result : Result<BaseResponseModel<ForgotPassDM>, 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()
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) {
let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.oTPVC) as! OTPVC
vc.vm.userName = self.vc.usernameTF.text!
self.vc.navigationController?.pushViewController(vc, animated: true)
}
default:
break
}
case .failure(let error):
Utilities.dismissProgressHUD()
self.vc.toast(msg: error.localizedDescription, time: 2)
}
}
}
}

View File

@@ -0,0 +1,112 @@
// Copyright (c) 2017 Cœur
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import UIKit
/**
* Simple UICollectionViewFlowLayout that centers the cells rather than justify them
*
* Based on https://github.com/Coeur/UICollectionViewLeftAlignedLayout
*/
open class CollectionViewCenteredFlowLayout: UICollectionViewFlowLayout {
open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let layoutAttributesForElements = super.layoutAttributesForElements(in: rect) else {
return nil
}
guard let collectionView = collectionView else {
return layoutAttributesForElements
}
// we group copies of the elements from the same row/column
var representedElements: [UICollectionViewLayoutAttributes] = []
var cells: [[UICollectionViewLayoutAttributes]] = [[]]
var previousFrame: CGRect?
if scrollDirection == .vertical {
for layoutAttributes in layoutAttributesForElements {
guard layoutAttributes.representedElementKind == nil else {
representedElements.append(layoutAttributes)
continue
}
// copying is required to avoid "UICollectionViewFlowLayout cache mismatched frame"
let currentItemAttributes = layoutAttributes.copy() as! UICollectionViewLayoutAttributes
// if the current frame, once stretched to the full row doesn't intersect the previous frame then they are on different rows
if previousFrame != nil && !currentItemAttributes.frame.intersects(CGRect(x: -.greatestFiniteMagnitude, y: previousFrame!.origin.y, width: .infinity, height: previousFrame!.size.height)) {
cells.append([])
}
cells[cells.endIndex - 1].append(currentItemAttributes)
previousFrame = currentItemAttributes.frame
}
// we reposition all elements
return representedElements + cells.flatMap { group -> [UICollectionViewLayoutAttributes] in
guard let section = group.first?.indexPath.section else {
return group
}
let evaluatedSectionInset = evaluatedSectionInsetForSection(at: section)
let evaluatedMinimumInteritemSpacing = evaluatedMinimumInteritemSpacingForSection(at: section)
let evaluatedCollectionView = (collectionView.bounds.width + evaluatedSectionInset.left - evaluatedSectionInset.right - group.reduce(0, { $0 + $1.frame.size.width }) - CGFloat(group.count - 1) * evaluatedMinimumInteritemSpacing)
var origin = evaluatedCollectionView / 2
// we reposition each element of a group
return group.map {
$0.frame.origin.x = origin
origin += $0.frame.size.width + evaluatedMinimumInteritemSpacing
return $0
}
}
} else {
for layoutAttributes in layoutAttributesForElements {
guard layoutAttributes.representedElementKind == nil else {
representedElements.append(layoutAttributes)
continue
}
// copying is required to avoid "UICollectionViewFlowLayout cache mismatched frame"
let currentItemAttributes = layoutAttributes.copy() as! UICollectionViewLayoutAttributes
// if the current frame, once stretched to the full column doesn't intersect the previous frame then they are on different columns
if previousFrame != nil && !currentItemAttributes.frame.intersects(CGRect(x: previousFrame!.origin.x, y: -.greatestFiniteMagnitude, width: previousFrame!.size.width, height: .infinity)) {
cells.append([])
}
cells[cells.endIndex - 1].append(currentItemAttributes)
previousFrame = currentItemAttributes.frame
}
// we reposition all elements
return representedElements + cells.flatMap { group -> [UICollectionViewLayoutAttributes] in
guard let section = group.first?.indexPath.section else {
return group
}
let evaluatedSectionInset = evaluatedSectionInsetForSection(at: section)
let evaluatedMinimumInteritemSpacing = evaluatedMinimumInteritemSpacingForSection(at: section)
let evaluatedCollectionView = (collectionView.bounds.height + evaluatedSectionInset.top - evaluatedSectionInset.bottom - group.reduce(0, { $0 + $1.frame.size.height }) - CGFloat(group.count - 1) * evaluatedMinimumInteritemSpacing)
var origin = evaluatedCollectionView / 2
// we reposition each element of a group
return group.map {
$0.frame.origin.y = origin
origin += $0.frame.size.height + evaluatedMinimumInteritemSpacing
return $0
}
}
}
}
}
extension UICollectionViewFlowLayout {
internal func evaluatedSectionInsetForSection(at section: Int) -> UIEdgeInsets {
(collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: section) ?? sectionInset
}
internal func evaluatedMinimumInteritemSpacingForSection(at section: Int) -> CGFloat {
(collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ?? minimumInteritemSpacing
}
}

View File

@@ -2,14 +2,21 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>STAGING_URL</key>
<string>$(STAGING_URL)</string>
<key>API_KEY_ID</key>
<string>$(API_KEY_ID)</string>
<key>API_KEY_PASS</key>
<string>$(API_KEY_PASS)</string>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>STAGING_URL</key>
<string>$(STAGING_URL)</string>
<key>UIAppFonts</key>
<array>
<string>Exo2-Bold.ttf</string>
<string>Exo2-ExtraBold.ttf</string>
<string>Exo2-Medium.ttf</string>
<string>Exo2-Regular.ttf</string>
<string>Exo2-SemiBold.ttf</string>
<string>Exo2-Thin.ttf</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
@@ -29,14 +36,5 @@
</array>
</dict>
</dict>
<key>UIAppFonts</key>
<array>
<string>Exo2-Bold.ttf</string>
<string>Exo2-ExtraBold.ttf</string>
<string>Exo2-Medium.ttf</string>
<string>Exo2-Regular.ttf</string>
<string>Exo2-SemiBold.ttf</string>
<string>Exo2-Thin.ttf</string>
</array>
</dict>
</plist>

View File

@@ -15,6 +15,9 @@ enum EnvironmentCheck{
struct APIEndPoints {
// Private init to prevent external initialization
private init() {}
struct BaseURL {
static let staging = "https://wokaland.com/admin/api/"
static let production = "https://simplitend.com"
@@ -31,6 +34,13 @@ struct APIEndPoints {
static let avatar_listing = makeURL(path: "avatar_listing")
static let child_registration = makeURL(path: "child_registration")
static let get_linked_child = makeURL(path: "get_linked_child")
/*
Password forgot api's
*/
static let forgot_password_send_otp = makeURL(path: "forgot_password_send_otp")
static let forgot_password_verify_otp = makeURL(path: "forgot_password_verify_otp")
static let update_password = makeURL(path: "update_password")
}
// Other endpoint categories...