Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

Rev 11 | Rev 18 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  LoginView.swift
3
//  twogetskills
4
//
5
//  Created by Efrain Yanez Recanatini on 1/27/22.
6
//
7
 
8
import SwiftUI
9
import AudioToolbox
10
import Network
11
import Alamofire
12
import SwiftyJSON
13
import SafariServices
14
import RNCryptor
15
 
16
 
17
 
18
 
19
 
20
struct SigninView: View {
21
 
22
    @EnvironmentObject var networkMonitor : NetworkMonitor
23
    @EnvironmentObject var appNavigation : AppNavigation
24
 
11 efrain 25
    @State private var keyboardHeight : CGFloat = 0
26
 
1 efrain 27
    private var appData = AppData.sharedInstance
28
 
29
 
17 efrain 30
    @State private var email: String = "efrain.yanez@leaderslinked.com" {
1 efrain 31
        didSet {
32
            if email.count > 250 {
33
                email = String(email.prefix(250))
34
                AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
35
            }
36
        }
37
    }
38
 
39
    @State private var isProcessing : Bool = false
40
 
41
    @State private var isValidEmail : Bool = true
42
    @State private var isEditingEmail : Bool = false
43
 
17 efrain 44
    @State private var password: String = "Cesa2020$"  {
1 efrain 45
        didSet {
46
            if password.count > 25 {
47
                password = String(password.prefix(25))
48
                AudioServicesPlayAlertSoundWithCompletion(SystemSoundID(kSystemSoundID_Vibrate)) { return }
49
            }
50
        }
51
    }
52
 
53
    @State private var isValidPassword : Bool = true
54
    @State private var isEditingPassword : Bool = false
55
 
56
    @State private var isPasswordShow: Bool = false
57
    @State private var showProgressView : Bool = false
58
 
59
    @State private var presentAlert : Bool = false
60
    @State private var titleAlert : String = ""
61
    @State private var messageAlert : String = ""
11 efrain 62
 
1 efrain 63
 
11 efrain 64
 
65
    @State private var openForgotPassword : Bool = false
66
    @State private var openSignup : Bool = false
67
 
1 efrain 68
    var body: some View {
69
        ZStack {
70
 
71
            Color("color_window_background")
72
                    .edgesIgnoringSafeArea(.all)
73
 
74
            if self.showProgressView {
75
                ProgressView()
76
                    .progressViewStyle(CircularProgressViewStyle(tint: Color("color_progress_view_foreground")))
77
                    .scaleEffect(3, anchor: .center).zIndex(100000)
78
            }
79
 
80
            VStack(spacing: 0) {
81
 
82
                if networkMonitor.status == .disconnected {
83
                    HStack {
84
 
85
 
86
                        Text(Config.LANG_ERROR_NETWORK_MESSAGE_SHORT)
87
                        .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_APP_BAR_HEAD1 ))
88
                            .foregroundColor(Color("color_network_disconnected_foreground"))
89
                            .padding(.leading, 16)
90
 
91
 
92
                        Spacer()
93
                    }
94
                    .edgesIgnoringSafeArea(.top)
95
                    .frame(height: 50)
96
                    .background(Color("color_network_disconnected_background"))
97
 
98
 
99
                    Divider().background(Color("color_network_disconnected_background"))
100
                }
101
 
102
                HeaderGroupView()
103
 
104
                EmailTextFieldGroup(email: self.$email, isEditingEmail: self.$isEditingEmail, isValidEmail: self.$isValidEmail, password: self.$password, isEditingPassword: self.$isEditingPassword, isValidPassword: self.$isValidPassword)
105
 
106
                PasswordTextFieldGroup(
107
                    password: self.$password,
108
                    isEditingPassword: self.$isEditingPassword,
109
                    isValidPassword: self.$isValidPassword,
110
                    isPasswordShow: self.$isPasswordShow
111
                ).padding(.top, isValidEmail ? 10 : 2)
112
 
113
 
114
 
115
                Button(action: {
116
                    if(validate()) {
117
                        signin()
118
                    }
119
                }, label: {
120
                    Text(Config.LANG_SIGNIN_BUTTON_SIGNIN)
121
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
122
                    .frame(width: UIScreen.main.bounds.width - 32, height: 35)
123
                    .foregroundColor(Color("color_button_foreground"))
124
                    .background(Color("color_button_background"))
125
                    .border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
126
                                           .cornerRadius(Config.BUTTON_BORDER_RADIUS)
127
 
128
                                   })
129
 
130
                                   .padding(.top, 16)
131
                                   .padding(.leading, 16)
132
                                   .padding(.trailing, 16)
133
 
134
 
11 efrain 135
                ButtonSignUpGroup(openSignup: self.$openSignup)
1 efrain 136
 
137
 
138
 
139
                Spacer()
140
 
11 efrain 141
                ButtonForgotPasswordGroup(openForgotPassword: self.$openForgotPassword)
142
 
1 efrain 143
 
144
            }
145
 
146
 
147
        }
148
 
149
        //}.offset(y : CGFloat(-(self.keyboardHeight / 2)))
150
 
151
        .onAppear {
152
    /*
153
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { (notification) in
154
                let keyboardHeight: CGFloat = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height ?? 0
155
 
156
 
157
                self.keyboardHeight = keyboardHeight
158
                //print("keyboardHeightShow = \(keyboardHeight)")
159
 
160
            }*/
161
 
162
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { (notification) in
163
 
164
 
165
               // print("keyboardHeightHide ")
166
 
167
            }
11 efrain 168
        }.popover(isPresented: self.$openSignup, content: {
169
 
170
            SafariView(sURL: Config.URL_SIGNUP_ENDPOINT)
171
 
172
        }).popover(isPresented: self.$openForgotPassword, content: {
173
 
174
            SafariView(sURL: Config.URL_FORGOT_PASSWORD_ENDPOINT)
175
 
176
        }).alert(isPresented: $presentAlert) {
1 efrain 177
            Alert(
178
                title: Text(self.titleAlert),
179
                message: Text(self.messageAlert),
180
                dismissButton: .default(Text(Config.LANG_COMMON_OK))
181
            )
182
        }
183
 
184
    }
185
 
186
    private func signin() -> Void
187
    {
188
        if isProcessing {
189
            self.titleAlert = Config.LANG_ERROR_SIGNIN_IN_PROGRESS_TITLE
190
            self.messageAlert = Config.LANG_ERROR_SIGNIN_IN_PROGRESS_MESSAGE
191
            self.presentAlert = true
192
 
193
            return
194
        }
195
 
196
 
197
        self.isEditingEmail = false
198
        self.isValidEmail = Validator.checkEmail(email: self.email)
199
        self.isEditingPassword = false
200
        self.isValidPassword = Validator.checkPassword(password: self.password)
201
 
202
        if !self.isValidEmail || !self.isValidPassword {
203
            return
204
        }
205
 
206
 
207
        let device_uuid = appData.deviceUuid
208
 
209
        //print("signin")
210
        //print(" aes  = \(appData.deviceAes) " )
211
        //print(" email  = \(self.email) " )
212
        //print(" password  = \(self.password) " )
213
 
214
 
17 efrain 215
        let syncDao = SyncDao()
1 efrain 216
        if appData.deviceAes.isEmpty  {
217
 
218
            let syncRecord = syncDao.selectOneByType(type: Constants.SYNC_ADAPTER_TYPE_DEVICE)
219
 
220
            if syncRecord.id > 0 {
221
                let syncAdapter = SyncAdapter()
17 efrain 222
                syncAdapter.sync(isForeground: true){
1 efrain 223
                    success in
224
                }
225
            }
226
 
227
            self.titleAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_TITLE
228
            self.messageAlert = Config.LANG_ERROR_DEVICE_NOT_REGISTER_MESSAGE
229
            self.presentAlert = true
230
 
231
            return
232
        }
233
 
234
 
235
 
236
        if networkMonitor.status == .disconnected {
237
            self.titleAlert = Config.LANG_ERROR_NETWORK_TITLE
238
            self.messageAlert = Config.LANG_ERROR_NETWORK_MESSAGE_SHORT
239
            self.presentAlert = true
240
 
241
            return
242
        }
243
 
244
        self.showProgressView = true;
245
 
246
        let emailData = email.data(using: .utf8)!
247
        let emailCipherData = RNCryptor.encrypt(data: emailData, withPassword: appData.deviceAes)
248
        let emailEncrypted = emailCipherData.base64EncodedString()
249
 
250
        let passwordData = password.data(using: .utf8)!
251
        let passwordCipherData = RNCryptor.encrypt(data: passwordData, withPassword: appData.deviceAes)
252
        let passwordEncrypted = passwordCipherData.base64EncodedString()
253
 
254
 
255
        //print(" email encrypted = \(emailEncrypted) " )
256
        //print(" password encrypted = \(passwordEncrypted) " )
257
 
258
        let parameters = [
17 efrain 259
            Constants.POST_SIGNIN_FIELD_APPLICATION_ID: "\(Config.APPLICATION_ID)",
260
            Constants.POST_SIGNIN_FIELD_VARIANT_ID: "\(Config.VARIANT_ID)",
1 efrain 261
            Constants.POST_SYNC_FIELD_DEVICE_UUID: device_uuid,
262
            Constants.POST_SIGNIN_FIELD_EMAIL: emailEncrypted,
263
            Constants.POST_SIGNIN_FIELD_PASSWORD: passwordEncrypted,
264
            Constants.POST_SIGNIN_FIELD_ENCRYPTER: Constants.GLOBAL_ENCRYPTER
265
        ]
266
 
267
        let headers: HTTPHeaders = [
268
            .accept(Constants.HTTP_HEADER_ACCEPT)
269
        ]
270
 
271
        //print("URL signin : \(Config.URL_SIGNIN)")
272
 
273
        self.showProgressView = true
274
        AF.request(Config.URL_SIGNIN, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{(response) in
275
            self.showProgressView = false
276
 
277
            switch response.result {
278
                case .success:
279
                    let json = try? JSON(data: response.data!)
280
 
281
                    //print("json : \(json)")
282
 
283
                    if json?["success"] ?? "" != false {
284
                        let dataService = DataService()
285
 
286
                        if dataService.syncFromServer(json : json) {
287
 
288
 
289
                            let userinfo = [
290
                                "title" : Config.LANG_TITLE_NOTIFICATION_SIGNIN_PUSH,
291
                                "body" : Config.LANG_BODY_NOTIFICATION_SIGNIN_PUSH,
292
                                "url" : ""
293
                            ]
294
 
295
 
296
                            NotificationCenter.default.post(name: Constants.NOTIFICATION_NAME_PUSH , object: self, userInfo: userinfo)
297
 
298
                            let now = Date()
299
                            let dateFormatter = DateFormatter()
300
                            dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
301
                            let dateOn = dateFormatter.string(from: now)
302
 
303
 
304
 
305
 
306
 
307
                            var userLog = UserLogModel()
308
                            userLog.userUuid = appData.userUuid
309
                            userLog.activity = Constants.USER_LOG_ACTIVITY_SIGNIN
310
                            userLog.addedOn = dateOn
311
 
17 efrain 312
                            let userLogDao = UserLogDao()
1 efrain 313
                            userLogDao.insert(record: userLog)
314
 
315
                            var sync = SyncModel()
316
 
317
                            var json = userLog.toJson()
318
                            json[Constants.SYNC_ADAPTER_DATA_TYPE_FIELD_NAME] = Constants.SYNC_ADAPTER_DATA_TYPE_USER_LOG
319
 
320
                            sync = SyncModel();
321
                            sync.type = Constants.SYNC_ADAPTER_TYPE_SYNC
322
                            if let theJSONData = try?  JSONSerialization.data(withJSONObject: json, options: .prettyPrinted),
323
                                let data = String(data: theJSONData, encoding: String.Encoding.ascii) {
324
                                    sync.data = data
325
                                }
326
 
327
                            syncDao.insert(record : sync);
328
 
329
 
330
                            appNavigation.subpageActive = AppMainSubPage.mycapsules
331
                            appNavigation.pageActive = AppMainPage.home
332
 
333
 
334
 
335
                            //self.goToMain = true
336
                        }
337
                    } else {
338
                        let message = json?["data"].string ?? ""
339
                        if !message.isEmpty {
340
                            self.titleAlert = Config.LANG_ERROR_GENERIC_TITLE
341
                            self.messageAlert = message
342
                            self.presentAlert = true
343
                        }
344
                    }
345
 
346
                   return
347
 
348
                case .failure :
349
                    self.titleAlert = Config.LANG_ERROR_COMMUNICATION_TITLE
350
                    self.messageAlert = Config.LANG_ERROR_COMMUNICATION_MESSAGE
351
                    self.presentAlert = true
352
 
353
                    return
354
            }
355
 
356
 
357
 
358
 
359
 
360
        }
361
    }
362
 
363
 
364
    private func validate() -> Bool
365
    {
366
 
367
        //print("validate - email : \(email)")
368
        //print("validate - password : \(password)")
369
 
370
 
371
        if email.isEmpty {
372
            self.isValidEmail = false
373
        } else  if !checkEmail(email: email) {
374
            self.isValidEmail = false
375
        } else {
376
            self.isValidEmail = true
377
        }
378
 
379
 
380
 
381
        if password.isEmpty {
382
            self.isValidPassword = false
383
        } else if(!checkPassword(password: password)) {
384
            self.isValidPassword = false
385
 
386
        } else {
387
            self.isValidPassword = true
388
        }
389
 
390
        return  self.isValidEmail &&  self.isValidPassword
391
    }
392
 
393
 
394
    private func checkEmail(email : String) -> Bool {
395
        let regex = #"^[a-zA-Z0-9_\-\.~]{2,}@[a-zA-Z0-9_\-\.~]{2,}\.[a-zA-Z]{2,}$"#
396
 
397
        let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
398
        return predicate.evaluate(with: email) ? true : false;
399
    }
400
 
401
    private func checkPassword(password : String) -> Bool {
402
        let regexOld = #"^(?=.*\d+)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,16}$"#
403
        let regexNew = #"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[\#\?\!\@\$\^\%\*\-]).{6,16}$"#
404
 
405
        let predicateNew = NSPredicate(format: "SELF MATCHES %@", regexNew)
406
        let predicateOld = NSPredicate(format: "SELF MATCHES %@", regexOld)
407
        if(predicateOld.evaluate(with: password)) {
408
            return true
409
        } else  if(predicateNew.evaluate(with: password)) {
410
            return true
411
        } else {
412
            return false
413
        }
414
    }
415
 
416
 
417
 
418
 
419
}
420
 
421
 
422
 
423
struct SigninView_Previews: PreviewProvider {
424
    static var previews: some View {
425
        SigninView()
426
    }
427
}
428
 
429
 
430
 
431
struct HeaderGroupView: View {
432
 
433
 
434
    var body: some View {
435
        //Inicio Logo
436
        HStack {
437
            Image("logo")
438
            .resizable()
439
            .frame(width: 50, height: 50)
440
 
441
            Text(Config.LANG_SIGNIN_APP_NAME)
442
            .font(Font.custom(Config.FONT_NAME_BOLD, size: 24))
443
            .foregroundColor(Color("color_textview_foreground"))
444
 
445
            Spacer()
446
        }
447
        .padding(.leading, 16)
448
        .padding(.top, 66)
449
        //Fin logo
450
 
451
        //Inicio Saludo
452
        HStack {
453
            Text(Config.LANG_SIGNIN_GREATING)
454
            .font(Font.custom(Config.FONT_NAME_BOLD, size: 32))
455
            .foregroundColor(Color("color_textview_foreground"))
456
            Spacer()
457
        }
458
        .padding(.leading, 16)
459
        .padding(.top, 10)
460
        //Fin Saludo
461
 
462
        //Inicio Encabezado
463
        HStack {
464
            Text(Config.LANG_SIGNIN_HEAD_LINE1)
465
            .font(Font.custom(Config.FONT_NAME_REGULAR, size: 16))
466
            .foregroundColor(Color("color_textview_foreground"))
467
            Spacer()
468
        }
469
        .padding(.leading, 16)
470
        .padding(.top, 10)
471
        //Fin Encabezado
472
    }
473
}
474
 
475
struct EmailTextFieldGroup : View {
476
 
477
 
478
 
479
    @Binding var email: String
480
    @Binding var isEditingEmail : Bool
481
    @Binding var isValidEmail : Bool
482
 
483
    @Binding var password: String
484
    @Binding var isEditingPassword: Bool
485
    @Binding var isValidPassword: Bool
486
 
487
 
488
    var body : some View {
489
        //Inicio Label Email
490
        HStack {
491
            Text(Config.LANG_SIGNIN_TITLE_EMAIL_FIELD)
17 efrain 492
            .font(Font.custom(Config  .FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_LABEL))
1 efrain 493
            .foregroundColor(Color("color_textview_foreground"))
494
            Spacer()
495
        }
496
        .padding(.leading, 16)
497
        .padding(.top, 10)
498
        //Fin Label Email
499
 
500
        //Inicio TextField  Email
501
 
502
        Group {
503
            HStack {
504
                /*
505
                Image("ui_mail")
506
                .resizable()
507
                .frame(width: 24, height: 24)
508
                         .padding(.horizontal, 4)
509
                */
510
 
511
 
512
                TextField("",
513
                    text: self.$email,
514
                    onEditingChanged: { (changed) in
515
 
516
                        if changed {
517
 
518
                            if self.isEditingPassword {
519
                                self.isValidPassword = Validator.checkPassword(password: self.password)
520
                                self.isEditingPassword = false
521
                            }
522
 
523
 
524
                            self.isEditingEmail = true
525
                        } else {
526
                            self.isEditingEmail = false
527
                            self.isValidEmail = Validator.checkEmail(email: self.email)
528
                        }
529
 
530
                    }, onCommit: {
531
                        self.isEditingEmail = false
532
                        self.isValidEmail = Validator.checkEmail(email: self.email)
533
                    }
534
                )
535
 
17 efrain 536
                .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
1 efrain 537
                .textFieldStyle(PlainTextFieldStyle())
538
                .frame(height: 32)
539
                .keyboardType(.emailAddress)
540
                .autocapitalization(.none)
541
                //.foregroundColor(Color("color_textfield_foreground"))
542
                //.background(Color("color_textfield_background"))
543
                .padding(.leading, 4)
544
                Spacer()
545
 
546
            }
547
        }
548
 
549
        .foregroundColor(Color("color_textfield_foreground"))
550
        .background(Color("color_textfield_background"))
551
        .overlay(RoundedRectangle(cornerRadius: 5).stroke(
552
            Color(self.isEditingEmail ? "color_textfield_border_active" : self.isValidEmail ? "color_textfield_border" : "color_textfield_border_error" )
553
        ))
554
        .padding(.leading, 16)
555
        .padding(.trailing, 16)
556
        .padding(.top, self.isValidEmail ? 10 : 2)
557
 
558
 
559
        if !self.isValidEmail {
560
            HStack {
561
                Spacer()
562
 
563
                Text(Config.LANG_SIGNIN_ERROR_EMAIL_FIELD)
564
                .foregroundColor(.red)
17 efrain 565
                .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_ERROR))
1 efrain 566
 
567
            }
568
            .padding(.top, 5)
569
            .padding(.trailing, 16)
570
        }
571
 
572
        //Fin TextField Email
573
    }
574
 
575
}
576
 
577
 
578
 
579
struct PasswordTextFieldGroup : View {
580
    @Binding var password: String
581
    @Binding var isEditingPassword: Bool
582
    @Binding var isValidPassword: Bool
583
    @Binding var isPasswordShow: Bool
584
 
585
    var body : some View {
586
        //Inicio Label Password
587
        HStack {
588
            Text(Config.LANG_SIGNIN_TITLE_PASSWORD_FIELD)
17 efrain 589
                .font(Font.custom(Config  .FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_LABEL))
1 efrain 590
            .foregroundColor(Color("color_textview_foreground"))
591
            Spacer()
592
        }
593
        .padding(.leading, 16)
594
        //Fin Label Password
595
 
596
 
597
        //Inicio TextField  Password
598
 
599
        Group {
600
            HStack {
601
                /*
602
                Image("ui_key")
603
                .resizable()
604
                .frame(width: 24, height: 24)
605
                         .padding(.horizontal, 4)
606
                 */
607
                if isPasswordShow {
608
 
609
                    TextField("",
610
                        text: self.$password,
611
                        onEditingChanged: { (changed) in
612
 
613
                            if changed {
614
                                self.isEditingPassword = true
615
                            } else {
616
                                self.isEditingPassword = false
617
                                self.isValidPassword = Validator.checkPassword(password: self.password)
618
                            }
619
 
620
                        }, onCommit: {
621
                            self.isEditingPassword = false
622
                            self.isValidPassword = Validator.checkPassword(password:  self.password)
623
                        }
624
                    )
17 efrain 625
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
1 efrain 626
                    .textFieldStyle(PlainTextFieldStyle())
627
                    .frame(height: 32)
628
                        .keyboardType(.default)
629
                    .autocapitalization(.none)
630
                    /*
631
                    .foregroundColor(Color("color_textfield_foreground"))
632
                    .background(Color("color_textfield_background"))
633
 */
634
                    .padding(.leading, 4)
635
                    Spacer()
636
 
637
                    Button(action: {
638
                        self.isPasswordShow.toggle()
639
                    }, label: {
640
                        Image("ui_visibility_off")
641
                        .resizable()
642
                        .frame(width: 24, height: 24)
643
                                 .padding(.horizontal, 4)
644
                    })
645
                } else {
646
 
647
                    SecureField("", text: self.$password, onCommit: {
648
                        self.isEditingPassword = false
649
                        self.isValidPassword = Validator.checkPassword(password: self.password)
650
                    })
651
                    .onTapGesture {
652
                        self.isEditingPassword = true
653
                    }
17 efrain 654
                    .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD))
1 efrain 655
                    .textFieldStyle(PlainTextFieldStyle())
656
                    .frame(height: 32)
657
                        .keyboardType(.default)
658
                    .autocapitalization(.none)
659
                    /*
660
                    .foregroundColor(Color("color_textfield_foreground"))
661
                    .background(Color("color_textfield_background"))*/
662
                        .padding(.leading, 4)
663
                    Spacer()
664
 
665
                    Button(action: {
666
                        self.isPasswordShow.toggle()
667
                    }, label: {
668
                        Image("ui_visibility")
669
                        .resizable()
670
                        .frame(width: 24, height: 24)
671
                                 .padding(.horizontal, 4)
672
 
673
                    })
674
 
675
                }
676
 
677
                //
678
                //ui_visibility
679
 
680
            }
681
        }
682
        .foregroundColor(Color("color_textfield_foreground"))
683
        .background(Color("color_textfield_background"))
684
        .overlay(RoundedRectangle(cornerRadius: 5).stroke(
685
            Color(self.isEditingPassword ? "color_textfield_border_active" : self.isValidPassword ? "color_textfield_border" : "color_textfield_border_error" )
686
        ))
687
        .padding(.leading, 16)
688
        .padding(.trailing, 16)
689
        .padding(.top, 2)
690
 
691
        if !self.isValidPassword {
692
            HStack {
693
                Spacer()
694
 
695
                Text(Config.LANG_SIGNIN_ERROR_PASSWORD_FIELD)
696
                .foregroundColor(.red)
17 efrain 697
                .font(Font.custom(Config.FONT_NAME_REGULAR, size: Config.FONT_SIZE_TEXTFIELD_ERROR))
1 efrain 698
 
699
            }
700
            .padding(.top, 5)
701
            .padding(.trailing, 16)
702
        }
703
 
704
        //Fin TextField Password
705
 
706
 
707
    }
708
 
709
 
710
 
711
}
712
 
713
struct ButtonSignUpGroup : View {
11 efrain 714
    @Binding var openSignup : Bool
1 efrain 715
 
11 efrain 716
 
717
 
1 efrain 718
    var body : some View {
719
        Button(action: {
11 efrain 720
            openSignup = true
1 efrain 721
 
722
        }, label: {
723
            Text(Config.LANG_SIGNIN_BUTTON_SIGNUP)
724
             .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
725
             .frame(width: UIScreen.main.bounds.width - 32, height: 35)
726
                .foregroundColor(Color("color_button_foreground"))
727
                .background(Color("color_button_background"))
728
                .border(Color("color_button_border"), width: Config.BUTTON_BORDER_SIZE)
729
                .cornerRadius(Config.BUTTON_BORDER_RADIUS)
730
 
731
        })
732
        .padding(.top, 16)
733
        .padding(.leading, 16)
734
        .padding(.trailing, 16)
735
    }
736
}
737
 
738
struct ButtonForgotPasswordGroup : View {
11 efrain 739
    @Binding var openForgotPassword : Bool
740
 
1 efrain 741
    var body : some View {
742
        Button(action: {
11 efrain 743
            openForgotPassword = true
1 efrain 744
 
745
        }, label: {
746
            Text(Config.LANG_SIGNIN_BUTTON_FORGOT_PASSWORD)
747
             .font(Font.custom(Config.FONT_NAME_REGULAR, size: 13))
748
 
749
                .foregroundColor(Color("color_button_foreground"))
750
 
751
 
752
 
753
        })
754
        .padding(.vertical, 16)
755
    }
756
}
11 efrain 757