Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

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