Proyectos de Subversion Iphone Microlearning - Nuevo Interface

Rev

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