feat: Enhance registration flow with navigation buttons and error handling
This commit is contained in:
parent
569e1d6049
commit
b6a82438dd
|
@ -455,18 +455,19 @@ class AzureOCRService {
|
||||||
if (gender.contains('laki') ||
|
if (gender.contains('laki') ||
|
||||||
gender.contains('pria') ||
|
gender.contains('pria') ||
|
||||||
gender == 'l' ||
|
gender == 'l' ||
|
||||||
gender == 'male') {
|
gender == 'male' ||
|
||||||
extractedInfo['gender'] = 'Male';
|
gender == 'm') {
|
||||||
extractedInfo['jenis_kelamin'] = 'LAKI-LAKI';
|
extractedInfo['jenis_kelamin'] = 'LAKI-LAKI';
|
||||||
} else if (gender.contains('perempuan') ||
|
} else if (gender.contains('perempuan') ||
|
||||||
gender.contains('wanita') ||
|
gender.contains('wanita') ||
|
||||||
gender == 'p' ||
|
gender == 'p' ||
|
||||||
gender == 'female') {
|
gender == 'female' ||
|
||||||
extractedInfo['gender'] = 'Female';
|
gender == 'f' ||
|
||||||
|
gender == 'w') {
|
||||||
extractedInfo['jenis_kelamin'] = 'PEREMPUAN';
|
extractedInfo['jenis_kelamin'] = 'PEREMPUAN';
|
||||||
} else {
|
} else {
|
||||||
extractedInfo['gender'] = _normalizeCase(genderText);
|
// Default to LAKI-LAKI if gender can't be determined
|
||||||
extractedInfo['jenis_kelamin'] = _normalizeCase(genderText);
|
extractedInfo['jenis_kelamin'] = 'LAKI-LAKI';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1411,7 +1412,7 @@ class AzureOCRService {
|
||||||
// Check if KTP has all required fields
|
// Check if KTP has all required fields
|
||||||
bool isKtpValid(Map<String, String> extractedInfo) {
|
bool isKtpValid(Map<String, String> extractedInfo) {
|
||||||
// Required fields for KTP validation
|
// Required fields for KTP validation
|
||||||
final requiredFields = ['nik', 'nama', 'jenis_kelamin', 'kewarganegaraan'];
|
final requiredFields = ['nik', 'nama', 'kewarganegaraan'];
|
||||||
|
|
||||||
// Check that all required fields are present and not empty
|
// Check that all required fields are present and not empty
|
||||||
for (var field in requiredFields) {
|
for (var field in requiredFields) {
|
||||||
|
@ -1452,17 +1453,20 @@ class AzureOCRService {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // Gender should be either "L" or "P"
|
// // Gender should be either "L" or "P"
|
||||||
final gender = extractedInfo['jenis_kelamin'] ?? '';
|
// final gender = extractedInfo['jenis_kelamin'] ?? '';
|
||||||
if (gender.isEmpty || gender != 'LAKI-LAKI' || gender != 'PEREMPUAN') {
|
|
||||||
print('KTP validation failed: Missing or invalid gender');
|
// if (gender.isEmpty || (gender != 'LAKI-LAKI' && gender != 'PEREMPUAN')) {
|
||||||
return false;
|
// print('KTP validation failed: Missing or invalid gender');
|
||||||
}
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
// // Nationality should be "WNI"
|
// // Nationality should be "WNI"
|
||||||
final nationality = extractedInfo['kewarganegaraan'] ?? 'WNI';
|
final nationality = extractedInfo['kewarganegaraan'] ?? 'Wbi';
|
||||||
|
|
||||||
if (nationality.isEmpty || nationality != 'WNI') {
|
print('Nationality: $nationality');
|
||||||
print('KTP validation failed: Missing or invalid');
|
|
||||||
|
if (nationality.isEmpty || nationality != 'Wni') {
|
||||||
|
print('KTP validation failed: Missing or invalid nationality');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:sigap/src/features/personalization/data/repositories/profile_rep
|
||||||
import 'package:sigap/src/features/personalization/data/repositories/roles_repository.dart';
|
import 'package:sigap/src/features/personalization/data/repositories/roles_repository.dart';
|
||||||
import 'package:sigap/src/features/personalization/data/repositories/users_repository.dart';
|
import 'package:sigap/src/features/personalization/data/repositories/users_repository.dart';
|
||||||
import 'package:sigap/src/shared/widgets/state_screeen/state_screen.dart';
|
import 'package:sigap/src/shared/widgets/state_screeen/state_screen.dart';
|
||||||
|
import 'package:sigap/src/utils/constants/image_strings.dart';
|
||||||
import 'package:sigap/src/utils/constants/num_int.dart';
|
import 'package:sigap/src/utils/constants/num_int.dart';
|
||||||
import 'package:sigap/src/utils/helpers/network_manager.dart';
|
import 'package:sigap/src/utils/helpers/network_manager.dart';
|
||||||
import 'package:sigap/src/utils/popups/loaders.dart';
|
import 'package:sigap/src/utils/popups/loaders.dart';
|
||||||
|
@ -74,6 +75,8 @@ class FormRegistrationController extends GetxController {
|
||||||
final RxString submitMessage = RxString('');
|
final RxString submitMessage = RxString('');
|
||||||
final RxBool isSubmitSuccess = RxBool(false);
|
final RxBool isSubmitSuccess = RxBool(false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
@ -714,6 +717,17 @@ class FormRegistrationController extends GetxController {
|
||||||
try {
|
try {
|
||||||
isSubmitting.value = true;
|
isSubmitting.value = true;
|
||||||
|
|
||||||
|
// validate all controllers before proceeding
|
||||||
|
// if (!formKey!.currentState!.validate()) {
|
||||||
|
// TLoaders.errorSnackBar(
|
||||||
|
// title: 'Validation Error',
|
||||||
|
// message: 'Please fill in all required fields correctly.',
|
||||||
|
// );
|
||||||
|
// isSubmitting.value = false;
|
||||||
|
// submitMessage.value = 'Please fill in all required fields correctly.';
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
final isConnected = await NetworkManager.instance.isConnected();
|
final isConnected = await NetworkManager.instance.isConnected();
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
TLoaders.errorSnackBar(
|
TLoaders.errorSnackBar(
|
||||||
|
@ -721,6 +735,8 @@ class FormRegistrationController extends GetxController {
|
||||||
message: 'Please check your internet connection and try again.',
|
message: 'Please check your internet connection and try again.',
|
||||||
);
|
);
|
||||||
isSubmitting.value = false;
|
isSubmitting.value = false;
|
||||||
|
submitMessage.value =
|
||||||
|
'Failed to complete registration: No internet connection';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,8 +760,6 @@ class FormRegistrationController extends GetxController {
|
||||||
birthDate: _parseBirthDate(identityController.birthDateController.text),
|
birthDate: _parseBirthDate(identityController.birthDateController.text),
|
||||||
);
|
);
|
||||||
|
|
||||||
Logger().d('Created user model for update: ${updateUser.toJson()}');
|
|
||||||
|
|
||||||
// Check if NIK is already registered (but ignore if it's the current user's NIK)
|
// Check if NIK is already registered (but ignore if it's the current user's NIK)
|
||||||
final isNikTaken = await UserRepository.instance.isNikExists(
|
final isNikTaken = await UserRepository.instance.isNikExists(
|
||||||
updateProfile!.nik!,
|
updateProfile!.nik!,
|
||||||
|
@ -757,6 +771,7 @@ class FormRegistrationController extends GetxController {
|
||||||
message: 'NIK already registered to another user!',
|
message: 'NIK already registered to another user!',
|
||||||
);
|
);
|
||||||
isSubmitting.value = false;
|
isSubmitting.value = false;
|
||||||
|
submitMessage.value = 'NIK already registered to another user!';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,28 +788,27 @@ class FormRegistrationController extends GetxController {
|
||||||
message: 'Failed to update user profile. Please try again.',
|
message: 'Failed to update user profile. Please try again.',
|
||||||
);
|
);
|
||||||
isSubmitting.value = false;
|
isSubmitting.value = false;
|
||||||
|
submitMessage.value =
|
||||||
|
'Failed to update user profile. Please try again.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user metadata with common profile info
|
|
||||||
final metadata =
|
|
||||||
UserMetadataModel(profileStatus: 'completed').toAuthMetadataJson();
|
|
||||||
|
|
||||||
// Update metadata first
|
// Update metadata first
|
||||||
await userRepository.updateUserMetadata(metadata);
|
await userRepository.updateProfileStatus('completed');
|
||||||
|
|
||||||
Logger().d('User metadata updated successfully');
|
Logger().d('User metadata updated successfully');
|
||||||
|
|
||||||
isSubmitSuccess.value = true;
|
isSubmitSuccess.value = true;
|
||||||
submitMessage.value = 'Registration completed successfully';
|
// submitMessage.value = 'Registration completed successfully';
|
||||||
|
|
||||||
Get.off(
|
Get.off(
|
||||||
() => StateScreen(
|
() => StateScreen(
|
||||||
title: 'Registration Completed',
|
title: 'Registration Completed',
|
||||||
subtitle: 'Your registration has been successfully completed.',
|
subtitle: 'Your registration has been successfully completed.',
|
||||||
icon: Icons.check_circle,
|
image: TImages.womanHuggingEarth,
|
||||||
|
isSvg: true,
|
||||||
showButton: true,
|
showButton: true,
|
||||||
primaryButtonTitle: 'Go to Home',
|
primaryButtonTitle: 'Back to sign in',
|
||||||
onPressed: () => AuthenticationRepository.instance.screenRedirect(),
|
onPressed: () => AuthenticationRepository.instance.screenRedirect(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -546,15 +546,8 @@ class IdentityVerificationController extends GetxController {
|
||||||
// Save registration data using the centralized model
|
// Save registration data using the centralized model
|
||||||
void saveRegistrationData() async {
|
void saveRegistrationData() async {
|
||||||
try {
|
try {
|
||||||
// Call the appropriate registration update function based on user type
|
|
||||||
if (isOfficer) {
|
|
||||||
// For officers, use the officer registration update function
|
|
||||||
// mainController.updateOfficerRegistrationData();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular users, call the three required updates
|
// For regular users, call the three required updates
|
||||||
mainController.updateUserRegistrationData();
|
mainController.updateUserRegistrationData();
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
isDataSaved.value = false;
|
isDataSaved.value = false;
|
||||||
dataSaveMessage.value = 'Error saving registration data: $e';
|
dataSaveMessage.value = 'Error saving registration data: $e';
|
||||||
|
@ -564,8 +557,6 @@ class IdentityVerificationController extends GetxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
// Dispose form controllers
|
// Dispose form controllers
|
||||||
|
|
|
@ -48,7 +48,7 @@ class FacialVerificationService {
|
||||||
final detectedFaces = await _edgeFunctionService.detectFaces(image);
|
final detectedFaces = await _edgeFunctionService.detectFaces(image);
|
||||||
return detectedFaces.isNotEmpty;
|
return detectedFaces.isNotEmpty;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error detecting face: $e');
|
print('Error detecting face. Please try again later.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ class SelfieVerificationController extends GetxController {
|
||||||
await _compareWithIdCard();
|
await _compareWithIdCard();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dev.log('Face detection API error: $e', name: 'SELFIE_VERIFICATION');
|
dev.log('Face detection API error: $e', name: 'SELFIE_VERIFICATION');
|
||||||
selfieError.value = 'Error detecting face: $e';
|
selfieError.value = 'Error detecting face: Please try again.';
|
||||||
isVerifyingFace.value = false;
|
isVerifyingFace.value = false;
|
||||||
isSelfieValid.value = false;
|
isSelfieValid.value = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/main/registration_form_controller.dart';
|
||||||
import 'package:sigap/src/utils/validators/validation.dart';
|
import 'package:sigap/src/utils/validators/validation.dart';
|
||||||
|
|
||||||
class PersonalInfoController extends GetxController {
|
class PersonalInfoController extends GetxController {
|
||||||
|
@ -23,6 +24,8 @@ class PersonalInfoController extends GetxController {
|
||||||
final RxString bioError = ''.obs;
|
final RxString bioError = ''.obs;
|
||||||
final RxString addressError = ''.obs;
|
final RxString addressError = ''.obs;
|
||||||
|
|
||||||
|
final RxString personalInfoError = ''.obs; // General error for personal info
|
||||||
|
|
||||||
|
|
||||||
// Manual validation as fallback
|
// Manual validation as fallback
|
||||||
final RxBool isFormValid = RxBool(true);
|
final RxBool isFormValid = RxBool(true);
|
||||||
|
@ -113,6 +116,18 @@ class PersonalInfoController extends GetxController {
|
||||||
return isFormValid.value;
|
return isFormValid.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleNextStep(
|
||||||
|
GlobalKey<FormState> formKey,
|
||||||
|
FormRegistrationController mainController,
|
||||||
|
) {
|
||||||
|
if (!validate(formKey)) {
|
||||||
|
personalInfoError.value = 'Please fill the required information.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mainController.nextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void clearErrors() {
|
void clearErrors() {
|
||||||
firstNameError.value = '';
|
firstNameError.value = '';
|
||||||
lastNameError.value = '';
|
lastNameError.value = '';
|
||||||
|
|
|
@ -97,16 +97,26 @@ class FormRegistrationScreen extends StatelessWidget {
|
||||||
currentStep: controller.currentStep.value,
|
currentStep: controller.currentStep.value,
|
||||||
totalSteps: controller.totalSteps,
|
totalSteps: controller.totalSteps,
|
||||||
stepTitles: controller.getStepTitles(),
|
stepTitles: controller.getStepTitles(),
|
||||||
onStepTapped: controller.goToStep,
|
onStepTapped: (index) {
|
||||||
|
// If stepping forward, use nextStep() to validate
|
||||||
|
if (index > controller.currentStep.value) {
|
||||||
|
controller.nextStep();
|
||||||
|
} else {
|
||||||
|
// If stepping backward, just go to that step without validation
|
||||||
|
controller.goToStep(index);
|
||||||
|
}
|
||||||
|
},
|
||||||
style: StepIndicatorStyle.standard,
|
style: StepIndicatorStyle.standard,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add navigation buttons
|
||||||
|
|
||||||
Widget _buildStepContent(FormRegistrationController controller) {
|
Widget _buildStepContent(FormRegistrationController controller) {
|
||||||
final isOfficer = controller.selectedRole.value?.isOfficer ?? false;
|
final isOfficer = controller.selectedRole.value?.isOfficer ?? false;
|
||||||
|
|
||||||
// Different step content for officer vs viewer
|
// Different step content for officer vs viewer
|
||||||
if (isOfficer) {
|
if (isOfficer) {
|
||||||
// Officer registration flow (3 steps)
|
// Officer registration flow (3 steps)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/off
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/selfie_verification_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/selfie_verification_controller.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/viewer-information/personal_info_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/viewer-information/personal_info_controller.dart';
|
||||||
import 'package:sigap/src/shared/widgets/form/form_section_header.dart';
|
import 'package:sigap/src/shared/widgets/form/form_section_header.dart';
|
||||||
|
import 'package:sigap/src/shared/widgets/navigation/step_navigation_buttons.dart';
|
||||||
import 'package:sigap/src/utils/constants/colors.dart';
|
import 'package:sigap/src/utils/constants/colors.dart';
|
||||||
import 'package:sigap/src/utils/constants/sizes.dart';
|
import 'package:sigap/src/utils/constants/sizes.dart';
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ class IdentityVerificationStep extends StatelessWidget {
|
||||||
onPressed:
|
onPressed:
|
||||||
ctrl.isSavingData.value
|
ctrl.isSavingData.value
|
||||||
? null
|
? null
|
||||||
: () => _submitRegistrationData(controller, context),
|
: () => _submitRegistrationData(controller),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: TColors.primary,
|
backgroundColor: TColors.primary,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
|
@ -89,6 +90,18 @@ class IdentityVerificationStep extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
Obx(
|
||||||
|
() => StepNavigationButtons(
|
||||||
|
showPrevious: mainController.currentStep.value > 0,
|
||||||
|
isLastStep: false,
|
||||||
|
onPrevious: mainController.previousStep,
|
||||||
|
onNext: () => _submitRegistrationData(controller),
|
||||||
|
isLoading: mainController.isSubmitting.value,
|
||||||
|
errorMessage: mainController.submitMessage.value,
|
||||||
|
nextButtonText: 'Continue',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// Save Result Message
|
// Save Result Message
|
||||||
GetBuilder<IdentityVerificationController>(
|
GetBuilder<IdentityVerificationController>(
|
||||||
id: 'saveMessage',
|
id: 'saveMessage',
|
||||||
|
@ -474,10 +487,8 @@ class IdentityVerificationStep extends StatelessWidget {
|
||||||
// Submit registration data
|
// Submit registration data
|
||||||
void _submitRegistrationData(
|
void _submitRegistrationData(
|
||||||
IdentityVerificationController controller,
|
IdentityVerificationController controller,
|
||||||
BuildContext context,
|
|
||||||
) async {
|
) async {
|
||||||
|
// Call saveRegistrati`onData with all the collected data
|
||||||
// Call saveRegistrationData with all the collected data
|
|
||||||
controller.saveRegistrationData();
|
controller.saveRegistrationData();
|
||||||
|
|
||||||
// The rest of submission logic would be handled in the controller
|
// The rest of submission logic would be handled in the controller
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:get/get.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/main/registration_form_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/main/registration_form_controller.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/viewer-information/personal_info_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/viewer-information/personal_info_controller.dart';
|
||||||
import 'package:sigap/src/shared/widgets/form/form_section_header.dart';
|
import 'package:sigap/src/shared/widgets/form/form_section_header.dart';
|
||||||
|
import 'package:sigap/src/shared/widgets/navigation/step_navigation_buttons.dart';
|
||||||
import 'package:sigap/src/shared/widgets/text/custom_text_field.dart';
|
import 'package:sigap/src/shared/widgets/text/custom_text_field.dart';
|
||||||
import 'package:sigap/src/utils/constants/sizes.dart';
|
import 'package:sigap/src/utils/constants/sizes.dart';
|
||||||
import 'package:sigap/src/utils/validators/validation.dart';
|
import 'package:sigap/src/utils/validators/validation.dart';
|
||||||
|
@ -127,6 +128,20 @@ class PersonalInfoStep extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: TSizes.spaceBtwSections),
|
||||||
|
|
||||||
|
// Navigation buttons
|
||||||
|
Obx(
|
||||||
|
() => StepNavigationButtons(
|
||||||
|
showPrevious: mainController.currentStep.value > 0,
|
||||||
|
isLastStep: false,
|
||||||
|
onPrevious: mainController.previousStep,
|
||||||
|
onNext: () => controller.handleNextStep(formKey, mainController),
|
||||||
|
errorMessage: controller.personalInfoError.value,
|
||||||
|
nextButtonText: 'Continue',
|
||||||
|
)
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -805,6 +805,8 @@ class SelfieVerificationStep extends StatelessWidget {
|
||||||
SelfieVerificationController controller,
|
SelfieVerificationController controller,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
) {
|
) {
|
||||||
|
final isDark = THelperFunctions.isDarkMode(context);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case VerificationStatus.initial:
|
case VerificationStatus.initial:
|
||||||
case VerificationStatus.performingLiveness:
|
case VerificationStatus.performingLiveness:
|
||||||
|
@ -817,7 +819,7 @@ class SelfieVerificationStep extends StatelessWidget {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
title: 'Detecting Face',
|
title: 'Detecting Face',
|
||||||
icon: Icons.face_retouching_natural,
|
icon: Icons.face_retouching_natural,
|
||||||
customColor: TColors.primary,
|
customColor: isDark ? TColors.accent : TColors.primary,
|
||||||
);
|
);
|
||||||
|
|
||||||
case VerificationStatus.comparingWithID:
|
case VerificationStatus.comparingWithID:
|
||||||
|
@ -827,7 +829,7 @@ class SelfieVerificationStep extends StatelessWidget {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
title: 'Face Matching',
|
title: 'Face Matching',
|
||||||
icon: Icons.compare,
|
icon: Icons.compare,
|
||||||
customColor: TColors.primary,
|
customColor: isDark ? TColors.accent : TColors.primary,
|
||||||
);
|
);
|
||||||
|
|
||||||
case VerificationStatus.livenessCompleted:
|
case VerificationStatus.livenessCompleted:
|
||||||
|
|
Loading…
Reference in New Issue