fix: new condition flag for idCardType

This commit is contained in:
vergiLgood1 2025-05-26 05:06:35 +07:00
parent dd2bb57e42
commit a7652aadfb
2 changed files with 156 additions and 21 deletions

View File

@ -3,11 +3,13 @@ import 'dart:io';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:logger/logger.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sigap/src/cores/services/azure_ocr_service.dart';
import 'package:sigap/src/features/auth/data/models/face_model.dart';
import 'package:sigap/src/features/auth/data/models/kta_model.dart';
import 'package:sigap/src/features/auth/data/models/ktp_model.dart';
import 'package:sigap/src/features/auth/data/repositories/authentication_repository.dart';
class IdCardVerificationController extends GetxController {
// Singleton instance
@ -16,12 +18,49 @@ class IdCardVerificationController extends GetxController {
// Services
final AzureOCRService _ocrService = AzureOCRService();
final bool isOfficer;
// Store isOfficer as a reactive variable instead of a final field
final RxBool _isOfficer = RxBool(false);
bool get isOfficer => _isOfficer.value;
// Maximum allowed file size in bytes (4MB)
final int maxFileSizeBytes = 4 * 1024 * 1024; // 4MB in bytes
IdCardVerificationController({required this.isOfficer});
// Constructor that accepts initial isOfficer value but will be updated from user data
IdCardVerificationController({bool isOfficer = false}) {
_isOfficer.value = isOfficer;
Logger().i(
'IdCardVerificationController initialized with isOfficer: $_isOfficer',
);
// Fetch current user role when controller is created
fetchCurrentUserRole();
}
// Method to fetch current user role and update isOfficer flag
Future<void> fetchCurrentUserRole() async {
try {
final metadata = AuthenticationRepository.instance.authUser?.userMetadata;
if (metadata == null) {
Logger().w('User metadata is null, cannot determine role');
return;
}
// Ambil nilai is_officer
final bool isOfficer = metadata['is_officer'] == true;
// Simpan ke variabel observasi jika perlu
_isOfficer.value = isOfficer;
Logger().i('Updated isOfficer flag from user role: $isOfficer');
// Tampilkan jenis kartu identitas yang perlu diverifikasi
final String idCardType = isOfficer ? 'KTA' : 'KTP';
Logger().i('User should verify $idCardType based on role');
} catch (e) {
Logger().e('Error fetching current user role: $e');
// Keep the initial value if there's an error
}
}
// Local storage keys
static const String _kOcrResultsKey = 'ocr_results';
@ -64,26 +103,34 @@ class IdCardVerificationController extends GetxController {
try {
final prefs = await SharedPreferences.getInstance();
final String jsonData = jsonEncode(results);
final String idCardType = isOfficer ? 'KTA' : 'KTP';
Logger().i(
'Saving to local storage for ID card type: $idCardType (isOfficer=$isOfficer)',
);
await prefs.setString(_kOcrResultsKey, jsonData);
await prefs.setString(_kIdCardTypeKey, isOfficer ? 'KTA' : 'KTP');
await prefs.setString(_kIdCardTypeKey, idCardType);
// Also save the model
if (isOfficer && ktaModel.value != null) {
Logger().i('Saving KTA model to storage');
await prefs.setString(
_kOcrModelKey,
jsonEncode(ktaModel.value!.toJson()),
);
} else if (!isOfficer && ktpModel.value != null) {
Logger().i('Saving KTP model to storage');
await prefs.setString(
_kOcrModelKey,
jsonEncode(ktpModel.value!.toJson()),
);
}
print('OCR results saved to local storage: ${results.length} items');
print('ID Card Type saved: ${isOfficer ? 'KTA' : 'KTP'}');
Logger().i('OCR results saved to local storage: ${results.length} items');
Logger().i('ID Card Type saved: $idCardType');
} catch (e) {
print('Error saving OCR results to local storage: $e');
Logger().e('Error saving OCR results to local storage: $e');
}
}
@ -97,7 +144,7 @@ class IdCardVerificationController extends GetxController {
return decodedData.map((key, value) => MapEntry(key, value.toString()));
}
} catch (e) {
print('Error loading OCR results from local storage: $e');
Logger().e('Error loading OCR results from local storage: $e');
}
return {};
}
@ -191,41 +238,72 @@ class IdCardVerificationController extends GetxController {
}
try {
// Make sure we have the latest user role before proceeding
await fetchCurrentUserRole();
isVerifying.value = true;
final idCardType = isOfficer ? 'KTA' : 'KTP';
Logger().i(
'Starting ID card validation for ${isOfficer ? "KTA (Officer)" : "KTP (Citizen)"} - isOfficer flag: $isOfficer',
);
// Basic validation to check if the image is clear enough for OCR
bool isImageValid = false;
try {
// Process the ID card with OCR (still using Azure OCR)
Logger().i(
'About to process ID card image with OCR service - isOfficer flag: $isOfficer',
);
// Process the ID card with OCR
final result = await _ocrService.processIdCard(
idCardImage.value!,
isOfficer,
);
Logger().i(
'OCR processing completed for $idCardType - Data received: ${result.length} fields',
);
// Store the extraction results
extractedInfo.assignAll(result);
hasExtractedInfo.value = result.isNotEmpty;
// Save the OCR results to local storage
if (result.isNotEmpty) {
print('Saving OCR results to local storage...');
Logger().i('Saving $idCardType OCR results to local storage...');
await _saveOcrResultsToLocalStorage(result);
}
// Debug the extracted data
Logger().i('Card type being validated: $idCardType');
Logger().i('isOfficer flag: $isOfficer');
Logger().i('Extracted data: $result');
// Check if the extracted information is valid using our validation methods
if (isOfficer) {
Logger().i('Validating as KTA (Officer card)');
isImageValid = _ocrService.isKtaValid(result);
} else {
isImageValid = _ocrService.isKtpValid(result);
}
Logger().i('KTA validation result: $isImageValid');
// Create model from extracted data
if (isOfficer) {
// Create KTA model from extracted data
ktaModel.value = _ocrService.createKtaModel(result);
Logger().i('KTA model created: ${ktaModel.value != null}');
// Ensure KTP model is null
ktpModel.value = null;
} else {
Logger().i('Validating as KTP (Citizen card)');
isImageValid = _ocrService.isKtpValid(result);
Logger().i('KTP validation result: $isImageValid');
// Create KTP model from extracted data
ktpModel.value = _ocrService.createKtpModel(result);
Logger().i('KTP model created: ${ktpModel.value != null}');
// Ensure KTA model is null
ktaModel.value = null;
}
if (isImageValid) {
@ -233,10 +311,14 @@ class IdCardVerificationController extends GetxController {
isIdCardValid.value = true;
idCardValidationMessage.value =
'$idCardType image looks valid. Please confirm this is your $idCardType.';
Logger().i('$idCardType validation successful');
} else {
isIdCardValid.value = false;
idCardValidationMessage.value =
'Unable to verify your $idCardType clearly. Please ensure all text is visible and try again.';
Logger().i(
'$idCardType validation failed - unable to verify clearly',
);
}
} on SocketException catch (e) {
isIdCardValid.value = false;
@ -248,10 +330,16 @@ class IdCardVerificationController extends GetxController {
idCardValidationMessage.value =
'Network error occurred. Please try again later.';
}
Logger().e(
'Network error during $idCardType validation: ${e.toString()}',
);
} catch (processingError) {
isIdCardValid.value = false;
idCardValidationMessage.value =
'We\'re having trouble processing your $idCardType. Please try again with a clearer image.';
Logger().e(
'Processing error during $idCardType validation: ${processingError.toString()}',
);
}
} catch (e) {
isIdCardValid.value = false;
@ -265,14 +353,22 @@ class IdCardVerificationController extends GetxController {
'The verification is taking too long. Please try again later when the connection is better.';
} else {
// Generic but still user-friendly error message
final idCardType = isOfficer ? 'KTA' : 'KTP';
idCardValidationMessage.value =
'We encountered an issue during verification. Please try again later.';
'We encountered an issue during $idCardType verification. Please try again later.';
}
// Log the actual error for debugging (wouldn't be shown to the user)
print('ID Card validation error: ${e.toString()}');
Logger().e('ID Card validation error: ${e.toString()}');
} finally {
isVerifying.value = false;
// Final verification of which model is set
Logger().i(
'Final verification - Card type: ${isOfficer ? "KTA" : "KTP"}',
);
Logger().i('KTP model is null: ${ktpModel.value == null}');
Logger().i('KTA model is null: ${ktaModel.value == null}');
}
}
@ -304,7 +400,7 @@ class IdCardVerificationController extends GetxController {
await prefs.remove(_kOcrModelKey);
await prefs.remove(_kIdCardTypeKey);
} catch (e) {
print('Error clearing OCR results from local storage: $e');
Logger().e('Error clearing OCR results from local storage: $e');
}
}
@ -315,14 +411,14 @@ class IdCardVerificationController extends GetxController {
// Log storage data for debugging
SharedPreferences.getInstance().then((prefs) {
print('Storage check on confirmation:');
print(
Logger().i('Storage check on confirmation:');
Logger().i(
'OCR results: ${prefs.getString(_kOcrResultsKey)?.substring(0, 50)}...',
);
print(
Logger().i(
'OCR model: ${prefs.getString(_kOcrModelKey)?.substring(0, 50)}...',
);
print('ID card type: ${prefs.getString(_kIdCardTypeKey)}');
Logger().i('ID card type: ${prefs.getString(_kIdCardTypeKey)}');
});
}
}
@ -331,4 +427,25 @@ class IdCardVerificationController extends GetxController {
dynamic get verifiedIdCardModel {
return isOfficer ? ktaModel.value : ktpModel.value;
}
// Debug helper method - can be called from UI for troubleshooting
void debugControllerState() {
Logger().i('======= ID CARD VERIFICATION CONTROLLER STATE =======');
Logger().i('isOfficer: $isOfficer');
Logger().i('Current ID card type: ${isOfficer ? "KTA" : "KTP"}');
Logger().i('Has ID card image: ${idCardImage.value != null}');
Logger().i('Is ID card valid: ${isIdCardValid.value}');
Logger().i('Has confirmed ID card: ${hasConfirmedIdCard.value}');
Logger().i('Has extracted info: ${hasExtractedInfo.value}');
Logger().i('Extracted info fields: ${extractedInfo.length}');
Logger().i('KTP model null: ${ktpModel.value == null}');
Logger().i('KTA model null: ${ktaModel.value == null}');
Logger().i('================================================');
}
// Method to force update the isOfficer flag (useful for testing or if user role changes)
void updateIsOfficerFlag(bool value) {
Logger().i('Manually updating isOfficer flag from $isOfficer to $value');
_isOfficer.value = value;
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:sigap/src/features/auth/data/models/kta_model.dart';
import 'package:sigap/src/features/auth/data/models/ktp_model.dart';
import 'package:sigap/src/features/auth/presentasion/controllers/signup/main/registration_form_controller.dart';
@ -25,8 +26,25 @@ class IdCardVerificationStep extends StatelessWidget {
mainController.formKey = formKey;
final isOfficer = mainController.selectedRole.value?.isOfficer ?? false;
// Ensure controller's isOfficer flag matches mainController's selected role
if (controller.isOfficer != isOfficer) {
controller.updateIsOfficerFlag(isOfficer);
Logger().i(
'Updated controller isOfficer flag to match selected role: $isOfficer',
);
}
final String idCardType = isOfficer ? 'KTA' : 'KTP';
Logger().i(
'Building IdCardVerificationStep with isOfficer: $isOfficer (Card type: $idCardType)',
);
Logger().i('Controller isOfficer flag: ${controller.isOfficer}');
// Call the debug method to print full controller state
controller.debugControllerState();
return Form(
key: formKey,
child: Column(