feat(cms): implement structured tuition data normalization and editor

Refactor tuition data from a simple numeric array to a structured object
containing time labels and values. This allows for more flexible
charting and precise data entry in the CMS.
- Add `normalizeTuition`, `normalizeTuitionSeries`, and `normalizeTuitionPoint` to `admissionsController.js`
- Update `admissionsConfig.js` to use `objectList` for tuition data points instead of `stringList`
- Migrate existing tuition data in `admissions.json` to the new structured format
- Fix duplicate text in `admissions.json` grant amounts and descriptions
This commit is contained in:
Tống Thành Đạt
2026-04-22 03:48:02 +07:00
parent 5d0fae6d51
commit f26b072954
3 changed files with 112 additions and 19 deletions
+45 -1
View File
@@ -66,6 +66,50 @@ function normalizeCalculator(calculator) {
return nextCalculator;
}
function normalizeTuitionPoint(point, index) {
if (point && typeof point === "object" && !Array.isArray(point)) {
const numericValue = Number(point.value);
return {
time: String(point.time || point.label || `Year ${index + 1}`),
value: Number.isFinite(numericValue) && numericValue >= 0 ? numericValue : 0,
};
}
const numericValue = Number(point);
return {
time: `Year ${index + 1}`,
value: Number.isFinite(numericValue) && numericValue >= 0 ? numericValue : 0,
};
}
function normalizeTuitionSeries(series, index) {
const source = typeof series === "string" ? { label: series } : { ...(series || {}) };
const rawPoints = Array.isArray(source.points) && source.points.length
? source.points
: Array.isArray(source.values)
? source.values
: [];
return {
label: String(source.label || `Series ${index + 1}`).slice(0, 40),
color: String(source.color || "#0F172A"),
points: rawPoints.map(normalizeTuitionPoint),
};
}
function normalizeTuition(tuition) {
const nextTuition = { ...(tuition || {}) };
nextTuition.title = String(nextTuition.title || "");
nextTuition.chartTitle = String(nextTuition.chartTitle || "");
nextTuition.chartDescription = String(nextTuition.chartDescription || "");
nextTuition.series = Array.isArray(nextTuition.series)
? nextTuition.series.map(normalizeTuitionSeries)
: [];
return nextTuition;
}
function normalizeAdmissionsPayload(rawPayload) {
const payload = JSON.parse(JSON.stringify(rawPayload || {}));
@@ -78,7 +122,7 @@ function normalizeAdmissionsPayload(rawPayload) {
id: "eligibility",
};
payload.tuition = {
...(payload.tuition || {}),
...normalizeTuition(payload.tuition),
id: "tuition-breakdown",
};
payload.keyDates = {