Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

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