diff --git a/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java b/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java index 37cca3aac..60c43f08d 100644 --- a/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java +++ b/android/app/src/main/java/io/mosip/registration_client/api_services/GlobalConfigSettingsApi.java @@ -85,4 +85,43 @@ public void getGpsEnableFlag(@NonNull GlobalConfigSettingsPigeon.Result } result.success(gpsFlag); } + + @Override + public void getPRIDLength(@NonNull GlobalConfigSettingsPigeon.Result result) { + int pridLength = 0; + try { + pridLength = globalParamRepository.getCachedIntegerPRIDLength(); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Error fetching PRID length", e); + result.error(e); + } + result.success((long) pridLength); + } + + @Override + public void getUINLength(@NonNull GlobalConfigSettingsPigeon.Result result) { + int uinLength = 0; + try { + uinLength = globalParamRepository.getCachedIntegerUINLength(); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Error fetching UIN length", e); + result.error(e); + } + result.success((long) uinLength); + } + + @Override + public void getVIDLength(@NonNull GlobalConfigSettingsPigeon.Result result) { + int vidLength = 0; + try { + vidLength = globalParamRepository.getCachedIntegerVIDLength(); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Error fetching VID length", e); + result.error(e); + } + result.success((long) vidLength); + + } + + } \ No newline at end of file diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java index 7af09795e..b5d9d030d 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/constant/RegistrationConstants.java @@ -136,6 +136,11 @@ public class RegistrationConstants { public static final String REG_PAK_MAX_CNT_OFFLINE_FREQ = "mosip.registration.packet.maximum.count.offline.frequency"; public static final String INVALID_LOGIN_COUNT = "mosip.registration.invalid_login_count"; public static final String INVALID_LOGIN_TIME = "mosip.registration.invalid_login_time"; + public static final String DISK_SPACE = "mosip.registration.disk_space_size"; + public static final String PRID_LENGTH = "mosip.kernel.prid.length"; + public static final String UIN_LENGTH = "mosip.kernel.uin.length"; + public static final String VID_LENGTH = "mosip.kernel.vid.length"; + public static final String SUPERVISOR_APPROVAL_CONFIG_FLAG = "mosip.registration.supervisor_approval_config_flag"; public static final String DOC_TYPE = "mosip.registration.document_scanner_doctype"; public static final String APP_NAME = "mosip.registration.audit_application_name"; public static final String APP_ID = "mosip.registration.audit_application_id"; diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java index 5c08cd153..e76bdb2a8 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/repository/GlobalParamRepository.java @@ -212,6 +212,21 @@ public String getCachedStringInvalidLoginTime() { return globalParamMap.get(RegistrationConstants.INVALID_LOGIN_TIME); } + public int getCachedIntegerDiskSpaceSize() { + return getCachedIntegerGlobalParam(RegistrationConstants.DISK_SPACE); + } + + public int getCachedIntegerPRIDLength(){ + return getCachedIntegerGlobalParam(RegistrationConstants.PRID_LENGTH); + } + + public int getCachedIntegerUINLength(){ + return getCachedIntegerGlobalParam(RegistrationConstants.UIN_LENGTH); + } + + public int getCachedIntegerVIDLength(){ + return getCachedIntegerGlobalParam(RegistrationConstants.VID_LENGTH); + } public String getCachedStringDocType() { return globalParamMap.get(RegistrationConstants.DOC_TYPE); } diff --git a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java index 397c0a37f..c0b83600d 100644 --- a/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java +++ b/android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/RegistrationServiceImpl.java @@ -47,6 +47,7 @@ import io.mosip.registration.clientmanager.R; import io.mosip.registration.clientmanager.config.SessionManager; import io.mosip.registration.clientmanager.constant.Modality; +import io.mosip.registration.clientmanager.constant.PacketClientStatus; import io.mosip.registration.clientmanager.constant.RegistrationConstants; import io.mosip.registration.clientmanager.dto.CenterMachineDto; import io.mosip.registration.clientmanager.dto.ResponseDto; @@ -97,7 +98,7 @@ public class RegistrationServiceImpl implements RegistrationService { private static final String TAG = RegistrationServiceImpl.class.getSimpleName(); private static final String SOURCE = "REGISTRATION_CLIENT"; - private static final int MIN_SPACE_REQUIRED_MB = 50; + private static final int DEFAULT_MIN_SPACE_REQUIRED_MB = 50; private Context context; private RegistrationDto registrationDto; @@ -320,6 +321,14 @@ public void submitRegistrationDto(String makerName) throws Exception { registrationRepository.insertRegistration(this.registrationDto.getPacketId(), containerPath, centerMachineDto.getCenterId(), this.registrationDto.getProcess(), additionalInfo, this.registrationDto.getAdditionalInfoRequestId(), this.registrationDto.getRId(), this.registrationDto.getApplicationId()); + // Auto-approve when supervisor approval is disabled (flag not "Y") + String supervisorApprovalFlag = globalParamRepository.getCachedStringGlobalParam( + RegistrationConstants.SUPERVISOR_APPROVAL_CONFIG_FLAG); + if (supervisorApprovalFlag != null && !RegistrationConstants.ENABLE.equalsIgnoreCase(supervisorApprovalFlag.trim())) { + registrationRepository.updateStatus(this.registrationDto.getPacketId(), null, + PacketClientStatus.APPROVED.name()); + } + // Delete pre-registration record after successful packet creation if (this.registrationDto.getPreRegistrationId() != null && !this.registrationDto.getPreRegistrationId().trim().isEmpty()) { @@ -634,8 +643,13 @@ public List> getAudits() { private void doPreChecksBeforeRegistration(CenterMachineDto centerMachineDto) throws Exception { //free space validation + int minSpaceRequiredMB = globalParamRepository.getCachedIntegerDiskSpaceSize(); + if (minSpaceRequiredMB == 0) { + minSpaceRequiredMB = DEFAULT_MIN_SPACE_REQUIRED_MB; + } + long externalSpace = context.getExternalCacheDir().getUsableSpace(); - if ((externalSpace / (1024 * 1024)) < MIN_SPACE_REQUIRED_MB) + if ((externalSpace / (1024 * 1024)) < minSpaceRequiredMB) throw new ClientCheckedException(context, R.string.err_006); //is machine and center active diff --git a/assets/l10n/app_ar.arb b/assets/l10n/app_ar.arb index cee73533e..cf8ae2b36 100644 --- a/assets/l10n/app_ar.arb +++ b/assets/l10n/app_ar.arb @@ -315,6 +315,14 @@ "application_id_not_exist": "معرف التطبيق غير موجود!", "correct_application_id": "يرجى التحقق من معرف التطبيق الذي تم إدخاله أو إدخال معرف صحيح ومحاولة جلبه مرة أخرى.", "enter_application_id": "الرجاء إدخال معرف التطبيق", + "prid_length_greater": "يجب أن يتكون معرف التطبيق من أرقام {length} بالضبط", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "تمام", "no_internet_connection": "لا يوجد اتصال بالإنترنت!", "connect_and_retry": "يرجى الاتصال بالإنترنت وإعادة المحاولة.", diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb index 40a829e60..efa7b6449 100644 --- a/assets/l10n/app_en.arb +++ b/assets/l10n/app_en.arb @@ -315,6 +315,14 @@ "application_id_not_exist": "Application ID does not exist!", "correct_application_id": "Please check the entered Application ID or enter a correct ID and try to fetch it again.", "enter_application_id": "Please Enter Application ID", + "prid_length_greater": "Application ID must be exactly {length} digits.", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "OKAY", "no_internet_connection": "No Internet Connection!", "connect_and_retry": "Please connect with internet and retry.", diff --git a/assets/l10n/app_fr.arb b/assets/l10n/app_fr.arb index e828d66c0..a85c0ed96 100644 --- a/assets/l10n/app_fr.arb +++ b/assets/l10n/app_fr.arb @@ -315,6 +315,14 @@ "application_id_not_exist": "L'ID de l'application n'existe pas!", "correct_application_id": "Veuillez vérifier l'ID d'application saisi ou saisir un ID correct et essayer de le récupérer à nouveau.", "enter_application_id": "Veuillez saisir l'ID de la demande", + "prid_length_greater": "L'ID de l'application doit contenir exactement {length} chiffres", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "D'ACCORD", "no_internet_connection": "Pas de connexion Internet!", "connect_and_retry": "Veuillez vous connecter à Internet et réessayer.", diff --git a/assets/l10n/app_hi.arb b/assets/l10n/app_hi.arb index 08a1be72c..493e73d3d 100644 --- a/assets/l10n/app_hi.arb +++ b/assets/l10n/app_hi.arb @@ -315,6 +315,14 @@ "application_id_not_exist": "एप्लिकेशन आईडी मौजूद नहीं है!", "correct_application_id": "कृपया दर्ज की गई एप्लिकेशन आईडी की जांच करें या सही आईडी दर्ज करें और इसे दोबारा लाने का प्रयास करें।", "enter_application_id": "कृपया आवेदन आईडी दर्ज करें", + "prid_length_greater": "एप्लिकेशन आईडी बिल्कुल {length} अंकों की होनी चाहिए।", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "ठीक है", "no_internet_connection": "कोई इंटरनेट कनेक्शन नहीं!", "connect_and_retry": "कृपया इंटरनेट से जुड़ें और पुनः प्रयास करें।", diff --git a/assets/l10n/app_kn.arb b/assets/l10n/app_kn.arb index db0a4ec1d..17b3fb116 100644 --- a/assets/l10n/app_kn.arb +++ b/assets/l10n/app_kn.arb @@ -315,6 +315,14 @@ "application_id_not_exist": "ಅಪ್ಲಿಕೇಶನ್ ಐಡಿ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ!", "correct_application_id": "ದಯವಿಟ್ಟು ನಮೂದಿಸಿದ ಅಪ್ಲಿಕೇಶನ್ ಐಡಿಯನ್ನು ಪರಿಶೀಲಿಸಿ ಅಥವಾ ಸರಿಯಾದ ಐಡಿಯನ್ನು ನಮೂದಿಸಿ ಮತ್ತು ಅದನ್ನು ಮತ್ತೆ ಪಡೆಯಲು ಪ್ರಯತ್ನಿಸಿ.", "enter_application_id": "ದಯವಿಟ್ಟು ಅಪ್ಲಿಕೇಶನ್ ಐಡಿಯನ್ನು ನಮೂದಿಸಿ", + "prid_length_greater": "ಅಪ್ಲಿಕೇಶನ್ ID ನಿಖರವಾಗಿ {length} ಅಂಕೆಗಳಾಗಿರಬೇಕು.", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "ಸರಿ", "no_internet_connection": "ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ!", "connect_and_retry": "ದಯವಿಟ್ಟು ಇಂಟರ್ನೆಟ್\u200Cನೊಂದಿಗೆ ಸಂಪರ್ಕಿಸಿ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಿ.", diff --git a/assets/l10n/app_ta.arb b/assets/l10n/app_ta.arb index 929e0f550..040863dc5 100644 --- a/assets/l10n/app_ta.arb +++ b/assets/l10n/app_ta.arb @@ -324,6 +324,14 @@ "application_id_not_exist": "விண்ணப்ப ஐடி இல்லை", "correct_application_id": "உள்ளிட்ட விண்ணப்ப ஐடியைச் சரிபார்க்கவும் அல்லது சரியான ஐடியை உள்ளிட்டு, அதை மீண்டும் பெற முயற்சிக்கவும்.", "enter_application_id": "விண்ணப்ப ஐடியை உள்ளிடவும்", + "prid_length_greater": "விண்ணப்ப ஐடி சரியாக {length} இலக்கங்களாக இருக்க வேண்டும்.", + "@prid_length_greater": { + "placeholders": { + "length": { + "type": "int" + } + } + }, "okay": "சரி", "no_internet_connection": "இணைய இணைப்பு இல்லை!", "connect_and_retry": "இணையத்துடன் இணைத்து மீண்டும் முயற்சிக்கவும்.", diff --git a/lib/platform_android/global_config_service_impl.dart b/lib/platform_android/global_config_service_impl.dart index b8d472285..ac39b5ada 100644 --- a/lib/platform_android/global_config_service_impl.dart +++ b/lib/platform_android/global_config_service_impl.dart @@ -71,6 +71,45 @@ class GlobalConfigServiceImpl implements GlobalConfigService { return gpsEnableFlag; } + @override + Future getPRIDLength() async { + int pridLength = 0; + try { + pridLength = await GlobalConfigSettingsApi().getPRIDLength(); + } on PlatformException { + debugPrint("PRID Length Api failed!"); + } catch (e) { + debugPrint("PRID Length fetch error: $e"); + } + return pridLength; + } + + @override + Future getUINLength() async { + int uinLength = 0; + try { + uinLength = await GlobalConfigSettingsApi().getUINLength(); + } on PlatformException { + debugPrint("UIN Length Api failed!"); + } catch (e) { + debugPrint("UIN Length fetch error: $e"); + } + return uinLength; + } + + @override + Future getVIDLength() async { + int vidLength = 0; + try { + vidLength = await GlobalConfigSettingsApi().getVIDLength(); + } on PlatformException { + debugPrint("VID Length Api failed!"); + } catch (e) { + debugPrint("VID Length fetch error: $e"); + } + return vidLength; + } + } GlobalConfigService getGlobalConfigServiceImpl() => GlobalConfigServiceImpl(); \ No newline at end of file diff --git a/lib/platform_spi/global_config_service.dart b/lib/platform_spi/global_config_service.dart index eb481ff4f..029fcf1c6 100644 --- a/lib/platform_spi/global_config_service.dart +++ b/lib/platform_spi/global_config_service.dart @@ -11,5 +11,11 @@ abstract class GlobalConfigService { Future getGpsEnableFlag(); + Future getPRIDLength(); + + Future getUINLength(); + + Future getVIDLength(); + factory GlobalConfigService() => getGlobalConfigServiceImpl(); } \ No newline at end of file diff --git a/lib/provider/global_provider.dart b/lib/provider/global_provider.dart index 391a1ff69..16914d4f2 100644 --- a/lib/provider/global_provider.dart +++ b/lib/provider/global_provider.dart @@ -122,6 +122,10 @@ class GlobalProvider with ChangeNotifier { _checkAgeGroupChange = value; } + int? _pridLength; + int? _uinLength; + int? _vidLength; + //GettersSetters setScannedPages(String field, List value) { _scannedPages[field] = value; @@ -146,6 +150,10 @@ class GlobalProvider with ChangeNotifier { String get ageGroup => _ageGroup; + int? get pridLength => _pridLength; + int? get uinLength => _uinLength; + int? get vidLength => _vidLength; + set scannedPages(Map> value) { _scannedPages = value; notifyListeners(); @@ -500,6 +508,24 @@ class GlobalProvider with ChangeNotifier { } } + getPRIDLength() async { + int length = await globalConfigService.getPRIDLength(); + _pridLength = length == 0 ? 14 : length; + notifyListeners(); + } + + getUINLength() async { + int length = await globalConfigService.getUINLength(); + _uinLength = length == 0 ? 10 : length; + notifyListeners(); + } + + getVIDLength() async { + int length = await globalConfigService.getVIDLength(); + _vidLength = length == 0 ? 16 : length; + notifyListeners(); + } + chooseLanguage(Map label) { String x = ''; for (var i in chosenLang) { diff --git a/lib/ui/process_ui/widgets/pre_reg_data_control.dart b/lib/ui/process_ui/widgets/pre_reg_data_control.dart index 466e72c87..756235519 100644 --- a/lib/ui/process_ui/widgets/pre_reg_data_control.dart +++ b/lib/ui/process_ui/widgets/pre_reg_data_control.dart @@ -37,6 +37,7 @@ class _PreRegDataControlState extends State { if(globalProvider.preRegId!=""){ preRegIdController.text = globalProvider.preRegId; } + globalProvider.getPRIDLength(); super.initState(); } @@ -199,6 +200,7 @@ class _PreRegDataControlState extends State { Widget build(BuildContext context) { bool isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + GlobalProvider globalProvider = Provider.of(context); return Card( elevation: 5, color: pureWhite, @@ -233,6 +235,19 @@ class _PreRegDataControlState extends State { //preRegIdController.text = value; globalProvider.setPreRegistrationId(value); }, + validator: (value) { + if (value == null || value.isEmpty) { + return null; // Empty validation handled by button click + } + if (globalProvider.pridLength != null) { + // Check if length matches configured value + if (value.length > globalProvider.pridLength!) { + return AppLocalizations.of(context)! + .prid_length_greater(globalProvider.pridLength!); + } + } + return null; + }, textAlign: TextAlign.left, decoration: InputDecoration( border: OutlineInputBorder( @@ -259,6 +274,10 @@ class _PreRegDataControlState extends State { ), onPressed: () async { widget.onFetched(); + // Validate form field first + if (!_formFieldKey.currentState!.validate()) { + return; + } if(preRegIdController.text.isEmpty){ globalProvider.preRegControllerRefresh = true; showDialog( @@ -266,21 +285,34 @@ class _PreRegDataControlState extends State { builder: (BuildContext context) => ValidatorAlert(errorMessage: AppLocalizations.of(context)!.enter_application_id), ); globalProvider.preRegControllerRefresh = false; - } else if(!RegExp(r'^\d{14}$').hasMatch(preRegIdController.text)){ - globalProvider.preRegControllerRefresh = true; - showDialog( - context: context, - builder: (BuildContext context) => ValidatorAlert(errorMessage: AppLocalizations.of(context)!.application_id_not_exist,subError: AppLocalizations.of(context)!.correct_application_id), - ); - await context.read< - RegistrationTaskProvider>() - .fetchPreRegistrationDetail( - preRegIdController.text); - - globalProvider.clearMap(); - globalProvider.clearScannedPages(); - globalProvider.preRegControllerRefresh = false; } else { + // Validate length using config value + bool isValidLength = true; + if (globalProvider.pridLength != null) { + String input = preRegIdController.text; + if (input.length != globalProvider.pridLength! || !RegExp(r'^\d+$').hasMatch(input)) { + isValidLength = false; + } + } + + if (!isValidLength) { + globalProvider.preRegControllerRefresh = true; + showDialog( + context: context, + builder: (BuildContext context) => ValidatorAlert( + errorMessage: AppLocalizations.of(context)!.application_id_not_exist, + subError: AppLocalizations.of(context)!.correct_application_id + ), + ); + await context.read< + RegistrationTaskProvider>() + .fetchPreRegistrationDetail( + preRegIdController.text); + + globalProvider.clearMap(); + globalProvider.clearScannedPages(); + globalProvider.preRegControllerRefresh = false; + } else { globalProvider.preRegControllerRefresh = true; Map value = await context.read< RegistrationTaskProvider>() @@ -296,6 +328,7 @@ class _PreRegDataControlState extends State { globalProvider.clearScannedPages(); globalProvider.preRegControllerRefresh = false; } + } } }, child: Text( @@ -322,14 +355,29 @@ class _PreRegDataControlState extends State { builder: (context) => QRCodeScannerApp()), ); - if(data!=null && !RegExp(r'^\d{14}$').hasMatch(data)){ - globalProvider.preRegControllerRefresh = true; - showDialog( - context: context, - builder: (BuildContext context) => ValidatorAlert(errorMessage: AppLocalizations.of(context)!.application_id_not_exist,subError: AppLocalizations.of(context)!.correct_application_id), - ); - globalProvider.preRegControllerRefresh = false; - } else if(data!=null) { + if(data!=null) { + // Validate scanned data length + bool isValidLength = true; + if (globalProvider.pridLength != null) { + String scannedData = data.toString(); + if (scannedData.length != globalProvider.pridLength! || !RegExp(r'^\d+$').hasMatch(scannedData)) { + isValidLength = false; + } + } else { + // Fallback to default validation if config not loaded + if (!RegExp(r'^\d{14}$').hasMatch(data)) { + isValidLength = false; + } + } + + if (!isValidLength) { + globalProvider.preRegControllerRefresh = true; + showDialog( + context: context, + builder: (BuildContext context) => ValidatorAlert(errorMessage: AppLocalizations.of(context)!.application_id_not_exist,subError: AppLocalizations.of(context)!.correct_application_id), + ); + globalProvider.preRegControllerRefresh = false; + } else { globalProvider.preRegControllerRefresh = true; setState(() { preRegIdController.text = data.toString(); @@ -349,11 +397,11 @@ class _PreRegDataControlState extends State { globalProvider.clearScannedPages(); globalProvider.preRegControllerRefresh = false; } + } } }, child: Icon(Icons.crop_free,size: 32.6,color: solidPrimary), ), - //const Spacer(), ], ) diff --git a/lib/ui/process_ui/widgets/update_field_selector.dart b/lib/ui/process_ui/widgets/update_field_selector.dart index d1c122ab5..a56c84ea6 100644 --- a/lib/ui/process_ui/widgets/update_field_selector.dart +++ b/lib/ui/process_ui/widgets/update_field_selector.dart @@ -36,9 +36,12 @@ class _UpdateFieldSelectorState extends State late GlobalProvider globalProvider; late RegistrationTaskProvider registrationTaskProvider; Map> fieldsMap = {}; - final RegExp validation = RegExp(r'^([0-9]{10})$'); + final RegExp inputValidation = RegExp(r'^[0-9]+$'); TextEditingController controller = TextEditingController(); late AppLocalizations appLocalizations = AppLocalizations.of(context)!; + int? uinLength; + int? vidLength; + String? idSubType; @override void initState() { @@ -46,6 +49,10 @@ class _UpdateFieldSelectorState extends State registrationTaskProvider = Provider.of(context, listen: false); controller = TextEditingController(text: globalProvider.updateUINNumber); + + // Fetch UIN and VID lengths from backend + _initializeUINVIDLength(); + for (var screen in widget.process.screens!) { for (var field in screen!.fields!) { if (field!.group != null) { @@ -54,6 +61,14 @@ class _UpdateFieldSelectorState extends State } fieldsMap[field.group]!.add(field); } + + // Determine ID subType from available fields + if (field.subType != null && idSubType == null) { + String subType = field.subType!.toLowerCase(); + if (subType == "uin" || subType == "vid") { + idSubType = subType; + } + } } } super.initState(); @@ -75,6 +90,21 @@ class _UpdateFieldSelectorState extends State )); } + + Future _initializeUINVIDLength() async { + await globalProvider.getUINLength(); + await globalProvider.getVIDLength(); + + // Update local variables after fetching from backend + // Use default values if null: UIN = 10, VID = 16 + if (mounted) { + setState(() { + uinLength = globalProvider.uinLength ?? 10; + vidLength = globalProvider.vidLength ?? 16; + }); + } + } + _getFieldTitle(Field field) { String title = ""; if (field.groupLabel == null) { @@ -180,11 +210,22 @@ class _UpdateFieldSelectorState extends State globalProvider.updateUINNumber = value; }, validator: (value) { - if (value == null) { + if (value == null || value.isEmpty) { return appLocalizations.valid_uin; - } else if (!validation.hasMatch(value)) { + } + + // Determine validation length based on available field subType in UI spec + int? expectedLength = idSubType == "vid" ? vidLength : uinLength; + // Check if length matches the expected length + if (expectedLength != null && value.length != expectedLength) { return appLocalizations.valid_uin; } + + // Check if value contains only digits + if (!inputValidation.hasMatch(value)) { + return appLocalizations.valid_uin; + } + return null; }, decoration: InputDecoration( diff --git a/pigeon/global_config_settings.dart b/pigeon/global_config_settings.dart index 0c2e8f379..6bbb06d5e 100644 --- a/pigeon/global_config_settings.dart +++ b/pigeon/global_config_settings.dart @@ -12,4 +12,10 @@ abstract class GlobalConfigSettingsApi { void modifyConfigurations(Map localPreferences); @async String getGpsEnableFlag(); + @async + int getPRIDLength(); + @async + int getUINLength(); + @async + int getVIDLength(); } \ No newline at end of file