Proyectos de Subversion Iphone Microlearning - Nuevo Interface

Rev

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