Proyectos de Subversion Iphone Microlearning - Nuevo Interface

Rev

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