Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"devDependencies": {
"@egovernments/digit-ui-libraries": "1.8.15",
"@egovernments/digit-ui-components": "0.2.0-beta.45",
"@egovernments/digit-ui-module-core": "1.8.44",
"@egovernments/digit-ui-module-core": "1.8.55",
"@egovernments/digit-ui-module-utilities": "1.0.12",
"@egovernments/digit-ui-react-components": "1.8.21",
"@egovernments/digit-ui-module-health-pgr": "0.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useCreateComplaint from "./pgr/useCreateComplaint";
import usePGRSearch from "./pgr/usePGRSearch";
import usePGRUpdate from "./pgr/usePGRUpdate";
import useServiceDefs from "./pgr/useServiceDefs";
import useMobileValidation from "./pgr/useMobileValidation";

const pgr = {
useProjectSearch,
Expand All @@ -15,6 +16,7 @@ const pgr = {
usePGRSearch,
usePGRUpdate,
useServiceDefs,
useMobileValidation,
};


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { useQuery } from "react-query";

/**
* Custom hook to fetch mobile number validation configuration from MDMS
* Priority:
* 1. Global configs (window.globalConfigs?.getConfig("CORE_MOBILE_CONFIGS"))
* 2. MDMS configs (ValidationConfigs.mobileNumberValidation)
* 3. Default fallback validation
* @param {string} tenantId - The tenant ID
* @param {string} validationName - The validation name (default: "defaultMobileValidation")
* @returns {object} - Returns validation rules and loading state
*/
const useMobileValidation = (tenantId, validationName = "defaultMobileValidation") => {
const reqCriteria = {
url: `/mdms-v2/v1/_search`,
params: {
tenantId: tenantId,
},
body: {
MdmsCriteria: {
tenantId: tenantId,
"moduleDetails": [
{
"moduleName": "ValidationConfigs",
"masterDetails": [
{
"name": "mobileNumberValidation"
}
]
}
]
},
},
config: {
enabled: !!tenantId,
select: (data) => {
return data.MdmsRes;
},
},
};
// Fetch project staff details using custom API hook
const { isLoading, data, error } = Digit.Hooks.useCustomAPIHook(reqCriteria);

/** ---------- Priority 1: Global Config ---------- */
const globalConfig = window?.globalConfigs?.getConfig?.("CORE_MOBILE_CONFIGS") || {};


// Extract validation rules
const mdmsConfig = data?.ValidationConfigs?.mobileNumberValidation?.find(
(config) => config.validationName === validationName
);

// Default fallback validation if MDMS fails
const defaultValidation = {
validationName: "defaultMobileValidation",
rules: {
allowedStartingDigits: ["6", "7", "8", "9"],
prefix: "+91",
pattern: "^[6-9][0-9]{9}$",
minLength: 10,
maxLength: 10,
errorMessage: "Please enter a valid 10-digit mobile number starting with 6-9",
isActive: true,
},
};

/** ---------- Combine configs with priority ---------- */
const validationRules = {
allowedStartingDigits:
globalConfig?.mobileNumberAllowedStartingDigits || mdmsConfig?.rules?.allowedStartingDigits || defaultValidation?.rules?.allowedStartingDigits,

prefix:
globalConfig?.mobilePrefix ||
mdmsConfig?.rules?.prefix ||
defaultValidation?.rules?.prefix,

pattern:
globalConfig?.mobileNumberPattern ||
mdmsConfig?.rules?.pattern ||
defaultValidation?.rules?.pattern,

minLength:
globalConfig?.mobileNumberLength ||
mdmsConfig?.rules?.minLength ||
defaultValidation?.rules?.minLength,

maxLength:
globalConfig?.mobileNumberLength ||
mdmsConfig?.rules?.maxLength ||
defaultValidation?.rules?.maxLength,

errorMessage:
globalConfig?.mobileNumberErrorMessage || mdmsConfig?.rules?.errorMessage || defaultValidation?.rules?.errorMessage,

isActive: (mdmsConfig && mdmsConfig.rules && mdmsConfig.rules.isActive !== undefined)
? mdmsConfig.rules.isActive
: (defaultValidation && defaultValidation.rules && defaultValidation.rules.isActive !== undefined)
? defaultValidation.rules.isActive
: true

};


// Helper function to get min/max values for number validation
const getMinMaxValues = () => {
const { allowedStartingDigits, minLength } = validationRules;
if (!allowedStartingDigits || allowedStartingDigits.length === 0) {
return { min: 0, max: 9999999999 };
}

const minDigit = Math.min(...allowedStartingDigits.map(Number));
const maxDigit = Math.max(...allowedStartingDigits.map(Number));

const min = minDigit * Math.pow(10, minLength - 1);
const max = (maxDigit + 1) * Math.pow(10, minLength - 1) - 1;

return { min, max };
};

return {
validationRules,
isLoading,
error,
getMinMaxValues,
};
};

export default useMobileValidation;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
import { Redirect, Route, Switch, useHistory, useRouteMatch, useLocation } from "react-router-dom";
import { FormComposerCitizen} from "@egovernments/digit-ui-components";
import { newConfig as baseConfig } from "./CreateCommonConfig";
import { Loader } from "@egovernments/digit-ui-components";

// import { newConfig } from "../../configs/IndividualCreateConfig";
// import { transformIndividualCreateData } from "../../utils/createUtils";
Expand All @@ -11,6 +12,10 @@ const IndividualCreateCitizen = () => {

const tenantId = Digit.ULBService.getCurrentTenantId();
const { t } = useTranslation();

// Fetch mobile validation config from MDMS
const { validationRules, isLoading: isValidationLoading, getMinMaxValues } = Digit.Hooks.pgr.useMobileValidation(tenantId);

const reqCreate = {
url: `/individual/v1/_create`,
params: {},
Expand All @@ -22,6 +27,40 @@ const IndividualCreateCitizen = () => {

const mutation = Digit.Hooks.useCustomAPIMutationHook(reqCreate);

// Inject mobile validation rules from MDMS into the config
const config = useMemo(() => {
if (!validationRules) return baseConfig;

const { min, max } = getMinMaxValues();

return baseConfig.map((section) => {
if (section.head === "Create Individual") {
return {
...section,
body: section.body.map((field) => {
if (field.key === "phno" && field.type === "number") {
return {
...field,
populators: {
...field.populators,
validation: {
min: min,
max: max,
minlength: validationRules.minLength,
maxlength: validationRules.maxLength,
pattern: validationRules.pattern,
},
error: validationRules.errorMessage || field.populators.error,
},
};
}
return field;
}),
};
}
return section;
});
}, [validationRules]);


const onFormSubmit = async (data) => {
Expand All @@ -36,10 +75,13 @@ const IndividualCreateCitizen = () => {
});
};

if (isValidationLoading) {
return <Loader />;
}

return (
<div>
<FormComposerCitizen config={baseConfig} onSubmit={onFormSubmit}
<FormComposerCitizen config={config} onSubmit={onFormSubmit}
onFormValueChange={(setValue, formData, formState, reset, setError, clearErrors, trigger, getValues) => {
console.log(formData, "formData");
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const CreateComplaint = () => {
const CreateComplaintSession = Digit.Hooks.useSessionStorage("COMPLAINT_CREATE", {});
const [sessionFormData, setSessionFormData, clearSessionFormData] = CreateComplaintSession;

// Fetch mobile validation config from MDMS
const { validationRules, isLoading: isValidationLoading, getMinMaxValues } = Digit.Hooks.pgr.useMobileValidation(tenantId);

// Fetch MDMS config for Create Complaint screen (RAINMAKER-PGR.CreateComplaintConfig)
const { data: mdmsData, isLoading } = Digit.Hooks.useCommonMDMS(
Digit.ULBService.getStateId(),
Expand All @@ -45,15 +48,53 @@ const CreateComplaint = () => {
// const serviceDefs = Digit.Hooks.pgr.useServiceDefs(tenantId, "PGR");

// Use MDMS config if available, otherwise fallback to local static config
const configs = mdmsData || CreateComplaintConfig?.CreateComplaintConfig?.[0];
let configs = mdmsData || CreateComplaintConfig?.CreateComplaintConfig?.[0];

/**
* Preprocess config using translation and inject complaint types into the serviceCode dropdown
* and inject mobile validation from MDMS
*/

// Inject mobile validation rules from MDMS into the config
if (configs && validationRules) {
const { min, max } = getMinMaxValues();
configs = {
...configs,
form: configs.form.map((section) => {
if (section.head === "ES_CREATECOMPLAINT_PROVIDE_COMPLAINANT_DETAILS") {
return {
...section,
body: section.body.map((field) => {
if (field.label === "COMPLAINTS_COMPLAINANT_CONTACT_NUMBER") {
return {
...field,
populators: {
...field.populators,
componentInFront: validationRules.prefix,
validation: {
required: true,
minlength: validationRules.minLength,
maxlength: validationRules.maxLength,
min: min,
max: max,
pattern: validationRules.pattern,
},
error: validationRules.errorMessage || "CORE_COMMON_MOBILE_ERROR",
},
};
}
return field;
}),
};
}
return section;
}),
};
}


// Show loader while fetching MDMS config
if (isLoading || !configs) {
if (isLoading || isValidationLoading || !configs) {
return <Loader />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const PGRSearchInbox = () => {
// Used to detect route/location changes to trigger config reset
const location = useLocation();

// Fetch mobile validation config from MDMS
const { validationRules, isLoading: isValidationLoading } = Digit.Hooks.pgr.useMobileValidation(tenantId);

// Fetch MDMS config for inbox screen (RAINMAKER-PGR.SearchInboxConfig)
const { data: mdmsData, isLoading } = Digit.Hooks.useCommonMDMS(
Digit.ULBService.getStateId(),
Expand All @@ -56,7 +59,43 @@ const PGRSearchInbox = () => {
);

// Fallback to static config if MDMS is not available
const configs = mdmsData || PGRSearchInboxConfig();
let configs = mdmsData || PGRSearchInboxConfig();

// Inject mobile validation rules from MDMS into the search config
if (configs && validationRules && configs.sections?.search?.uiConfig?.fields) {
const { min, max } = getMinMaxValues();
configs = {
...configs,
sections: {
...configs.sections,
search: {
...configs.sections.search,
uiConfig: {
...configs.sections.search.uiConfig,
fields: configs.sections.search.uiConfig.fields.map((field) => {
if (field.label === "CS_COMMON_MOBILE_NO" && field.populators?.name === "mobileNumber") {
return {
...field,
populators: {
...field.populators,
validation: {
minlength: validationRules.minLength,
maxlength: validationRules.maxLength,
min: min,
max: max,
pattern: validationRules.pattern,
},
error: validationRules.errorMessage || field.populators.error,
},
};
}
return field;
}),
},
},
},
};
}

// Fetch the list of service definitions (e.g., complaint types) for current tenant
const serviceDefs = Digit.Hooks.pgr.useServiceDefs(tenantId, "PGR");
Expand Down Expand Up @@ -92,7 +131,7 @@ const PGRSearchInbox = () => {
/**
* Show loader until necessary data is available
*/
if (isLoading || !pageConfig || serviceDefs?.length === 0) {
if (isLoading || isValidationLoading || !pageConfig || serviceDefs?.length === 0) {
return <Loader />;
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/micro-ui/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"homepage": "/digit-ui",
"dependencies": {
"@egovernments/digit-ui-libraries": "1.8.14",
"@egovernments/digit-ui-module-core": "1.8.44",
"@egovernments/digit-ui-module-core": "1.8.55",
"@egovernments/digit-ui-module-utilities": "1.0.12",
"@egovernments/digit-ui-react-components": "1.8.21",
"@egovernments/digit-ui-svg-components": "1.0.21",
Expand Down