Skip to content

Commit 19aa047

Browse files
committed
Merge remote-tracking branch 'upstream/release-1.15.0' into release-1.15.0
2 parents 4be4e2d + 45bf7ed commit 19aa047

File tree

1 file changed

+266
-6
lines changed
  • mfes/scp-teacher-repo/src/pages/centers

1 file changed

+266
-6
lines changed

mfes/scp-teacher-repo/src/pages/centers/index.tsx

Lines changed: 266 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,67 @@ import SimpleModal from '@/components/SimpleModalV2';
4747
import AddEditUser from '@/components/EntityForms/AddEditUser/AddEditUser';
4848
import { fetchForm } from '@/components/DynamicForm/DynamicFormCallback';
4949

50+
const toUpperString = (value: unknown) =>
51+
typeof value === 'string' ? value.toUpperCase() : '';
52+
53+
const asString = (value: unknown): string | null => {
54+
if (typeof value === 'string') return value;
55+
if (value && typeof value === 'object' && 'value' in (value as any)) {
56+
const v = (value as any).value;
57+
return typeof v === 'string' ? v : null;
58+
}
59+
return null;
60+
};
61+
62+
const uniqStrings = (values: Array<string | null | undefined>) =>
63+
Array.from(new Set(values.filter((v): v is string => !!v)));
64+
65+
const getCustomFieldEntry = (customField: any[] | undefined, label: string) => {
66+
const target = label.toUpperCase();
67+
return (customField || []).find(
68+
(item) => toUpperString(item?.label) === target
69+
);
70+
};
71+
72+
const getCustomFieldValues = (customField: any[] | undefined, label: string) => {
73+
const entry = getCustomFieldEntry(customField, label);
74+
const selectedValues = Array.isArray(entry?.selectedValues)
75+
? entry.selectedValues
76+
: [];
77+
78+
// Some APIs use `value` (string) instead of `selectedValues`.
79+
if (selectedValues.length === 0 && entry?.value) {
80+
return uniqStrings([asString(entry.value)]);
81+
}
82+
83+
return uniqStrings(selectedValues.map((v: any) => asString(v) ?? v));
84+
};
85+
86+
const getCustomFieldSingleValue = (
87+
customField: any[] | undefined,
88+
label: string
89+
) => {
90+
const values = getCustomFieldValues(customField, label);
91+
return values?.[0] || null;
92+
};
93+
94+
const findCohortById = (items: any, cohortId: string): any | null => {
95+
if (!cohortId) return null;
96+
const stack: any[] = Array.isArray(items) ? [...items] : [];
97+
98+
while (stack.length) {
99+
const node = stack.pop();
100+
if (!node) continue;
101+
102+
if (node?.cohortId === cohortId) return node;
103+
104+
const children = Array.isArray(node?.childData) ? node.childData : [];
105+
for (const child of children) stack.push(child);
106+
}
107+
108+
return null;
109+
};
110+
50111
const CentersPage = () => {
51112
const { t } = useTranslation();
52113
const theme = useTheme<any>();
@@ -86,9 +147,12 @@ const CentersPage = () => {
86147
const [centerList, setCenterList] = useState<any[]>([]);
87148
const userStore = manageUserStore();
88149
const [openBatchModal, setOpenBatchModal] = useState(false);
150+
const [baseBatchSchema, setBaseBatchSchema] = useState<any>(null);
151+
const [baseBatchUiSchema, setBaseBatchUiSchema] = useState<any>(null);
89152
const [addBatchSchema, setAddBatchSchema] = useState<any>(null);
90153
const [addBatchUiSchema, setAddBatchUiSchema] = useState<any>(null);
91154
const [emptyFormData, setEmptyFormData] = useState<any>({});
155+
const [batchPrefillFormData, setBatchPrefillFormData] = useState<any>({});
92156
const [tempVariable, setTempVariable] = useState([]);
93157

94158
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
@@ -230,7 +294,9 @@ const CentersPage = () => {
230294
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
231295
const location = getLocationFromCustomFields(userData);
232296
// console.log('location', location);
233-
setEmptyFormData({...location, name: ''});
297+
const base = { ...location, name: '' };
298+
setEmptyFormData(base);
299+
setBatchPrefillFormData(base);
234300
}, [tempVariable]);
235301

236302
useEffect(() => {
@@ -417,6 +483,141 @@ const CentersPage = () => {
417483
}
418484
};
419485

486+
const cloneDeep = <T,>(obj: T): T => JSON.parse(JSON.stringify(obj));
487+
488+
const buildBatchCreateConfigForCenter = (params: {
489+
baseSchema: any;
490+
baseUiSchema: any;
491+
parentId: string;
492+
parentName?: string | null;
493+
centerType: string | null;
494+
boards: string[];
495+
mediums: string[];
496+
grades: string[];
497+
}) => {
498+
const schema = cloneDeep(params.baseSchema);
499+
const uiSchema = cloneDeep(params.baseUiSchema);
500+
501+
const parentSchema = schema?.properties?.parentId;
502+
const parentIsArray =
503+
parentSchema?.type === 'array' || typeof parentSchema?.items === 'object';
504+
const prefill: any = {
505+
parentId: parentIsArray ? [params.parentId] : params.parentId,
506+
};
507+
508+
// Ensure parentId validates against schema (enum/api often comes from remote lists).
509+
if (schema?.properties?.parentId) {
510+
const parentLabel = params.parentName || 'Center';
511+
if (schema.properties.parentId?.api) delete schema.properties.parentId.api;
512+
if (schema.properties.parentId?.items?.api)
513+
delete schema.properties.parentId.items.api;
514+
515+
if (parentIsArray) {
516+
schema.properties.parentId.items = {
517+
...(schema.properties.parentId.items || {}),
518+
type: 'string',
519+
enum: [params.parentId],
520+
enumNames: [parentLabel],
521+
};
522+
} else {
523+
schema.properties.parentId.enum = [params.parentId];
524+
schema.properties.parentId.enumNames = [parentLabel];
525+
schema.properties.parentId.default = params.parentId;
526+
}
527+
}
528+
529+
// Hide parentId since it's derived from selected center dropdown.
530+
uiSchema.parentId = {
531+
...(uiSchema?.parentId || {}),
532+
'ui:widget': 'hidden',
533+
};
534+
535+
const ensureEnabled = (key: string) => {
536+
if (uiSchema?.[key]?.['ui:disabled']) {
537+
const next = { ...(uiSchema[key] || {}) };
538+
delete next['ui:disabled'];
539+
uiSchema[key] = next;
540+
}
541+
};
542+
543+
const overrideEnum = (key: 'board' | 'medium' | 'grade', allowed: any[]) => {
544+
const allowedValues = Array.isArray(allowed) ? allowed.filter(Boolean) : [];
545+
if (!allowedValues.length) {
546+
ensureEnabled(key);
547+
return;
548+
}
549+
550+
if (!schema?.properties?.[key]) return;
551+
552+
// Remove dynamic api source and restrict to center-allowed values.
553+
if (schema.properties[key]?.api) delete schema.properties[key].api;
554+
if (schema.properties[key]?.items?.api) delete schema.properties[key].items.api;
555+
556+
if (schema.properties[key]?.type === 'array' || schema.properties[key]?.items) {
557+
schema.properties[key].items = {
558+
...(schema.properties[key].items || {}),
559+
type: 'string',
560+
enum: allowedValues,
561+
enumNames: allowedValues,
562+
};
563+
} else {
564+
schema.properties[key].enum = allowedValues;
565+
schema.properties[key].enumNames = allowedValues;
566+
}
567+
568+
if (allowedValues.length === 1) {
569+
prefill[key] =
570+
schema.properties[key]?.type === 'array' || schema.properties[key]?.items
571+
? [allowedValues[0]]
572+
: allowedValues[0];
573+
uiSchema[key] = {
574+
...(uiSchema?.[key] || {}),
575+
'ui:disabled': true,
576+
};
577+
} else {
578+
ensureEnabled(key);
579+
}
580+
};
581+
582+
overrideEnum('board', params.boards);
583+
overrideEnum('medium', params.mediums);
584+
overrideEnum('grade', params.grades);
585+
586+
// Batch type behavior (if supported by schema), similar to admin app.
587+
const ct = (params.centerType || '').toLowerCase();
588+
if (schema?.properties?.batch_type) {
589+
if (ct === 'remote') {
590+
schema.properties.batch_type.enum = ['remote'];
591+
schema.properties.batch_type.enumNames = ['REMOTE'];
592+
schema.properties.batch_type.default = 'remote';
593+
prefill.batch_type = 'remote';
594+
uiSchema.batch_type = {
595+
...(uiSchema?.batch_type || {}),
596+
'ui:disabled': true,
597+
};
598+
} else if (ct === 'regular') {
599+
// Only restrict if enum exists; otherwise leave as-is.
600+
const existingEnum = Array.isArray(schema.properties.batch_type.enum)
601+
? schema.properties.batch_type.enum
602+
: null;
603+
if (existingEnum) {
604+
const allowed = ['regular', 'contact'].filter((v) =>
605+
existingEnum.includes(v)
606+
);
607+
if (allowed.length) {
608+
schema.properties.batch_type.enum = allowed;
609+
schema.properties.batch_type.enumNames = allowed.map((v) =>
610+
v.toUpperCase()
611+
);
612+
}
613+
}
614+
ensureEnabled('batch_type');
615+
}
616+
}
617+
618+
return { schema, uiSchema, prefill };
619+
};
620+
420621
console.log('filtered batches before render:', filteredBatches);
421622

422623
useEffect(() => {
@@ -436,7 +637,7 @@ const CentersPage = () => {
436637

437638
if (responseForm?.schema && responseForm?.uiSchema) {
438639
// Remove unnecessary fields for batch creation
439-
let alterSchema = responseForm?.schema;
640+
let alterSchema = cloneDeep(responseForm?.schema);
440641
let requiredArray = alterSchema?.required ?? [];
441642
const mustRequired = [
442643
'name',
@@ -493,17 +694,66 @@ const CentersPage = () => {
493694

494695
return updatedData;
495696
};
496-
const fieldsToHide = ['state', 'district', 'block'];
697+
const fieldsToHide = ['state', 'district', 'block', 'village'];
497698
const updatedData = hideFields(responseForm?.uiSchema, fieldsToHide);
498-
setAddBatchSchema(alterSchema);
499-
setAddBatchUiSchema(updatedData);
699+
const normalizedUi = cloneDeep(updatedData);
700+
const normalizedSchema = cloneDeep(alterSchema);
701+
setBaseBatchSchema(normalizedSchema);
702+
setBaseBatchUiSchema(normalizedUi);
703+
setAddBatchSchema(normalizedSchema);
704+
setAddBatchUiSchema(normalizedUi);
500705
}
501706
};
502707

503708
fetchBatchFormSchema();
504709
}, []);
505710

506711
const handleOpenAddBatchModal = () => {
712+
if (!selectedCenter) {
713+
showToastMessage(t('COMMON.PLEASE_SELECT_THE_CENTER'), 'error');
714+
return;
715+
}
716+
717+
const effectiveBaseSchema = baseBatchSchema || addBatchSchema;
718+
const effectiveBaseUiSchema = baseBatchUiSchema || addBatchUiSchema;
719+
if (!effectiveBaseSchema || !effectiveBaseUiSchema) {
720+
showToastMessage(t('COMMON.LOADING'), 'info');
721+
return;
722+
}
723+
724+
const selectedNode = findCohortById(centerList, selectedCenter);
725+
const cf = (selectedNode?.customField ||
726+
selectedNode?.customFields ||
727+
[]) as any[];
728+
729+
const boards = getCustomFieldValues(cf, 'BOARD');
730+
const mediums = getCustomFieldValues(cf, 'MEDIUM');
731+
const grades = getCustomFieldValues(cf, 'GRADE');
732+
const selectedCenterType =
733+
getCustomFieldSingleValue(cf, 'TYPE_OF_COHORT') ||
734+
getCustomFieldSingleValue(cf, 'TYPE_OF_CENTER');
735+
736+
const { schema, uiSchema, prefill } = buildBatchCreateConfigForCenter({
737+
baseSchema: effectiveBaseSchema,
738+
baseUiSchema: effectiveBaseUiSchema,
739+
parentId: selectedCenter,
740+
parentName:
741+
selectedNode?.cohortName ||
742+
selectedNode?.name ||
743+
selectedNode?.cohortName,
744+
centerType: selectedCenterType,
745+
boards,
746+
mediums,
747+
grades,
748+
});
749+
750+
setAddBatchSchema(schema);
751+
setAddBatchUiSchema(uiSchema);
752+
setBatchPrefillFormData({
753+
...(emptyFormData || {}),
754+
...(prefill || {}),
755+
});
756+
507757
setOpenBatchModal(true);
508758
const telemetryInteract = {
509759
context: {
@@ -745,6 +995,7 @@ const CentersPage = () => {
745995
id="dynamic-form-id"
746996
>
747997
<AddEditUser
998+
key={`${selectedCenter || 'no-center'}-batch-create`}
748999
SuccessCallback={() => {
7491000
if (selectedCenter) {
7501001
getBlocksByCenterId(selectedCenter, centerList).then((res) => {
@@ -756,7 +1007,7 @@ const CentersPage = () => {
7561007
}}
7571008
schema={addBatchSchema}
7581009
uiSchema={addBatchUiSchema}
759-
editPrefilledFormData={emptyFormData}
1010+
editPrefilledFormData={batchPrefillFormData}
7601011
isEdit={false}
7611012
isReassign={false}
7621013
editableUserId={emptyUserId}
@@ -773,7 +1024,16 @@ const CentersPage = () => {
7731024
telemetryUpdateKey="batch-updated-successfully"
7741025
failureUpdateMessage="BATCH.BATCH_UPDATE_FAILED"
7751026
isNotificationRequired={false}
1027+
notificationKey=""
1028+
notificationMessage=""
1029+
notificationContext={{}}
1030+
blockFieldId=""
1031+
districtFieldId=""
1032+
villageFieldId=""
1033+
centerFieldId=""
7761034
hideSubmit={true}
1035+
setButtonShow={() => {}}
1036+
isSteeper={false}
7771037
type="batch"
7781038
/>
7791039
</SimpleModal>

0 commit comments

Comments
 (0)