Skip to content

Commit 0e9a3fe

Browse files
Merge branch 'release-1.15.0' of github.com:tekdi/pratham2.0 into release-1.15.0
2 parents 31f9737 + 45bf7ed commit 0e9a3fe

File tree

8 files changed

+1319
-241
lines changed

8 files changed

+1319
-241
lines changed

apps/admin-app-repo/src/pages/user-mobilizer.tsx

Lines changed: 366 additions & 122 deletions
Large diffs are not rendered by default.

libs/shared-lib-v2/src/MapUser/WorkingVillageAssignmentWidget.tsx

Lines changed: 189 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ interface WorkingVillageAssignmentWidgetProps {
5959
onSelectionChange?: (centerId: string, selectedVillages: Set<string>, villagesByBlock: Record<string, Array<{ id: string; name: string; blockId: string; unavailable: boolean; assigned: boolean }>>) => void;
6060
hideConfirmButton?: boolean; // Hide the Confirm Assignment button
6161
onCenterOptionsChange?: (centerOptions: any[]) => void; // Callback to get center options
62+
// Restore props: keep existing behaviors unless enabled
63+
isForRestore?: boolean; // Flag to indicate restore/reactivate mode
64+
centerOptionsOverride?: Array<{ id: string; name: string; cohortMembershipId?: string; customFields?: any[] }>; // Override center dropdown options (e.g. from getCohortList)
6265
// Reassign props
6366
centerId?: string; // Center ID to pre-select in reassign flow
6467
existingWorkingVillageIds?: string; // Comma-separated string of existing village IDs (e.g., "648579, 648570")
@@ -75,6 +78,8 @@ const WorkingVillageAssignmentWidget: React.FC<WorkingVillageAssignmentWidgetPro
7578
onSelectionChange,
7679
hideConfirmButton = false,
7780
onCenterOptionsChange,
81+
isForRestore = false,
82+
centerOptionsOverride,
7883
centerId: propCenterId,
7984
existingWorkingVillageIds,
8085
isForReassign = false,
@@ -158,6 +163,44 @@ const WorkingVillageAssignmentWidget: React.FC<WorkingVillageAssignmentWidgetPro
158163
selectedValues: any[] | null;
159164
} | null>(null);
160165

166+
// Store center's CATCHMENT_AREA fetched via API in restore mode (keyed by centerId)
167+
const [restoreCenterCatchmentArea, setRestoreCenterCatchmentArea] = useState<{
168+
centerId: string;
169+
selectedValues: any[] | null;
170+
} | null>(null);
171+
172+
const __overrideCenterOptions = useMemo(() => {
173+
if (!Array.isArray(centerOptionsOverride)) return null;
174+
return centerOptionsOverride.map((c) => ({
175+
id: String(c.id),
176+
name: c.name?.trim?.() || String(c.name || c.id),
177+
stateId: null,
178+
districtId: null,
179+
blockId: null,
180+
villages: 0,
181+
blocks: 0,
182+
customFields: c.customFields || [],
183+
cohortMembershipId: c.cohortMembershipId,
184+
}));
185+
}, [centerOptionsOverride]);
186+
187+
// If center options are overridden (e.g. restore flow), use them and skip internal center loading.
188+
useEffect(() => {
189+
if (!Array.isArray(centerOptionsOverride)) return;
190+
191+
const centers = __overrideCenterOptions || [];
192+
setCenterOptions(centers);
193+
194+
// Auto-select center when only one option is available (consistent with LMP behavior)
195+
if (!selectedCenter) {
196+
if (propCenterId && centers.some((c: any) => c.id === propCenterId)) {
197+
setSelectedCenter(String(propCenterId));
198+
} else if (centers.length === 1) {
199+
setSelectedCenter(String(centers[0].id));
200+
}
201+
}
202+
}, [centerOptionsOverride, __overrideCenterOptions, propCenterId, selectedCenter]);
203+
161204
// Load villages for all catchment blocks
162205
const loadVillagesForBlocks = useCallback(async () => {
163206
const __seq = ++__villagesLoadSeqRef.current;
@@ -884,8 +927,10 @@ const WorkingVillageAssignmentWidget: React.FC<WorkingVillageAssignmentWidgetPro
884927

885928
// Load centers whenever state/district/block changes
886929
useEffect(() => {
930+
// If parent provides center options explicitly, do not call center-loading APIs
931+
if (Array.isArray(centerOptionsOverride)) return;
887932
loadCenters();
888-
}, [loadCenters]);
933+
}, [loadCenters, centerOptionsOverride]);
889934

890935
// Fetch selected center's CATCHMENT_AREA via API in reassign mode (so villages update when user changes center)
891936
useEffect(() => {
@@ -972,8 +1017,142 @@ const WorkingVillageAssignmentWidget: React.FC<WorkingVillageAssignmentWidgetPro
9721017
};
9731018
}, [isForReassign, selectedCenter]);
9741019

1020+
// Fetch selected center's CATCHMENT_AREA via API in restore mode
1021+
// (getCohortList centers may not include customFields, but villages need CATCHMENT_AREA)
1022+
useEffect(() => {
1023+
if (!isForRestore || !selectedCenter) {
1024+
setRestoreCenterCatchmentArea(null);
1025+
return;
1026+
}
1027+
1028+
// If current center already contains a usable CATCHMENT_AREA, no need to fetch
1029+
const currentCenter = centerOptions.find((c) => c.id === selectedCenter);
1030+
const existingCatchmentAreaField = currentCenter?.customFields?.find(
1031+
(field: any) =>
1032+
field?.label === 'CATCHMENT_AREA' &&
1033+
Array.isArray(field?.selectedValues) &&
1034+
field.selectedValues.length > 0
1035+
);
1036+
if (existingCatchmentAreaField?.selectedValues) {
1037+
setRestoreCenterCatchmentArea({
1038+
centerId: selectedCenter,
1039+
selectedValues: existingCatchmentAreaField.selectedValues,
1040+
});
1041+
return;
1042+
}
1043+
1044+
// Clear previous catchment while loading
1045+
setRestoreCenterCatchmentArea({ centerId: selectedCenter, selectedValues: null });
1046+
let isMounted = true;
1047+
const centerIdToFetch = selectedCenter;
1048+
1049+
const fetchCenterCatchmentArea = async () => {
1050+
try {
1051+
const tenantId = localStorage.getItem('tenantId') || '';
1052+
const token = localStorage.getItem('token') || '';
1053+
const academicYearId = localStorage.getItem('academicYearId') || '';
1054+
1055+
const response = await axios.post(
1056+
`${process.env.NEXT_PUBLIC_MIDDLEWARE_URL}/cohort/search`,
1057+
{
1058+
limit: 200,
1059+
offset: 0,
1060+
filters: {
1061+
type: 'COHORT',
1062+
status: ['active'],
1063+
cohortId: [centerIdToFetch],
1064+
},
1065+
},
1066+
{
1067+
headers: {
1068+
'Content-Type': 'application/json',
1069+
tenantId: tenantId,
1070+
Authorization: `Bearer ${token}`,
1071+
academicyearid: academicYearId,
1072+
},
1073+
}
1074+
);
1075+
1076+
if (!isMounted) return;
1077+
1078+
const cohortDetails = response?.data?.result?.results?.cohortDetails || [];
1079+
const center = cohortDetails.find((c: any) => c.cohortId === centerIdToFetch);
1080+
1081+
if (center && center.customFields) {
1082+
const catchmentAreaField = center.customFields.find(
1083+
(field: any) => field.label === 'CATCHMENT_AREA'
1084+
);
1085+
1086+
setRestoreCenterCatchmentArea({
1087+
centerId: centerIdToFetch,
1088+
selectedValues: catchmentAreaField?.selectedValues || null,
1089+
});
1090+
} else {
1091+
setRestoreCenterCatchmentArea({ centerId: centerIdToFetch, selectedValues: null });
1092+
}
1093+
} catch (error) {
1094+
console.error('Error fetching center CATCHMENT_AREA (restore):', error);
1095+
if (isMounted) {
1096+
setRestoreCenterCatchmentArea({ centerId: centerIdToFetch, selectedValues: null });
1097+
}
1098+
}
1099+
};
1100+
1101+
fetchCenterCatchmentArea();
1102+
1103+
return () => {
1104+
isMounted = false;
1105+
};
1106+
}, [isForRestore, selectedCenter, centerOptions]);
1107+
9751108
// Extract catchment blocks from selected center's CATCHMENT_AREA or fetched CATCHMENT_AREA (in reassign mode)
9761109
useEffect(() => {
1110+
// Priority 0: In restore mode, prefer fetched CATCHMENT_AREA for the currently selected center
1111+
if (
1112+
isForRestore &&
1113+
selectedCenter &&
1114+
restoreCenterCatchmentArea &&
1115+
restoreCenterCatchmentArea.centerId === selectedCenter &&
1116+
Array.isArray(restoreCenterCatchmentArea.selectedValues) &&
1117+
restoreCenterCatchmentArea.selectedValues.length > 0
1118+
) {
1119+
const extractedBlocks: Array<{
1120+
id: string | number;
1121+
name: string;
1122+
districtId: string | number;
1123+
districtName: string;
1124+
stateId: string | number;
1125+
stateName: string;
1126+
}> = [];
1127+
1128+
const __selectedValues = restoreCenterCatchmentArea.selectedValues;
1129+
__selectedValues.forEach((stateData: any) => {
1130+
const stateId = stateData.stateId;
1131+
const stateName = stateData.stateName || '';
1132+
if (stateData.districts && Array.isArray(stateData.districts)) {
1133+
stateData.districts.forEach((district: any) => {
1134+
const districtId = district.districtId;
1135+
const districtName = district.districtName || '';
1136+
if (district.blocks && Array.isArray(district.blocks)) {
1137+
district.blocks.forEach((block: any) => {
1138+
extractedBlocks.push({
1139+
id: block.id,
1140+
name: block.name || '',
1141+
districtId,
1142+
districtName,
1143+
stateId,
1144+
stateName,
1145+
});
1146+
});
1147+
}
1148+
});
1149+
}
1150+
});
1151+
1152+
setCatchmentBlocks(extractedBlocks);
1153+
return;
1154+
}
1155+
9771156
// Priority 1: In reassign mode, use fetched CATCHMENT_AREA for the currently selected center (fetched when selectedCenter changes)
9781157
if (
9791158
isForReassign &&
@@ -1090,7 +1269,15 @@ const WorkingVillageAssignmentWidget: React.FC<WorkingVillageAssignmentWidgetPro
10901269
});
10911270

10921271
setCatchmentBlocks(extractedBlocks);
1093-
}, [selectedCenter, centerOptions, isForReassign, propCenterId, reassignCenterCatchmentArea]);
1272+
}, [
1273+
selectedCenter,
1274+
centerOptions,
1275+
isForRestore,
1276+
restoreCenterCatchmentArea,
1277+
isForReassign,
1278+
propCenterId,
1279+
reassignCenterCatchmentArea,
1280+
]);
10941281

10951282
// Clear villages when center is reset to empty
10961283
useEffect(() => {

mfes/scp-teacher-repo/public/locales/en/common.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@
190190
"PLEASE_SELECT_AT_LEAST_ONE_BATCH": "Please select at least one batch",
191191
"PLEASE_SEARCH_AND_SELECT_USER": "Please search and select a user",
192192
"PLEASE_SELECT_CENTER": "Please select a center",
193+
"MAP_NEW": "Map New",
194+
"RESIGNED_FROM_COMPANY": "Resigned from Company",
195+
"MOVED_TO_DIFFERENT_ROLE": "Moved to Different Role",
196+
"DELETE_FROM_BATCH_WARNING": "I confirm I want to remove this user from batches as well",
193197
"COPY_REGISTRATION_LINK": "Copy Registration Link",
194198
"REGISTRATION_LINK_COPIED":"Registration link copied!\nShare this link with learners for program registration."
195199
},
@@ -684,7 +688,12 @@
684688
"GRADE_9": "Grade 9",
685689
"GRADE_10": "Grade 10",
686690
"GRADE_11": "Grade 11",
687-
"GRADE_12": "Grade 12"
691+
"GRADE_12": "Grade 12",
692+
"BELONG_TO": "belong to",
693+
"BELONG_TO_MULTIPLE_CENTERS": "belong to multiple centers",
694+
"WAS_BELONG_TO": "was belong to",
695+
"DO_YOU_WANT_TO_DELETE": "Do you want to delete from center as well?",
696+
"DO_YOU_WANT_TO_DELETE_MULTIPLE_CENTERS": "Do you want to delete from centers as well?"
688697
},
689698
"FORM_ERROR_MESSAGES": {
690699
"INVALID_INPUT": "Invalid Input.",

0 commit comments

Comments
 (0)