forked from UKSOURCE/cms.lams
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:
@@ -66,6 +66,50 @@ function normalizeCalculator(calculator) {
|
|||||||
return nextCalculator;
|
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) {
|
function normalizeAdmissionsPayload(rawPayload) {
|
||||||
const payload = JSON.parse(JSON.stringify(rawPayload || {}));
|
const payload = JSON.parse(JSON.stringify(rawPayload || {}));
|
||||||
|
|
||||||
@@ -78,7 +122,7 @@ function normalizeAdmissionsPayload(rawPayload) {
|
|||||||
id: "eligibility",
|
id: "eligibility",
|
||||||
};
|
};
|
||||||
payload.tuition = {
|
payload.tuition = {
|
||||||
...(payload.tuition || {}),
|
...normalizeTuition(payload.tuition),
|
||||||
id: "tuition-breakdown",
|
id: "tuition-breakdown",
|
||||||
};
|
};
|
||||||
payload.keyDates = {
|
payload.keyDates = {
|
||||||
|
|||||||
+43
-12
@@ -72,22 +72,53 @@
|
|||||||
{
|
{
|
||||||
"label": "Traditional University",
|
"label": "Traditional University",
|
||||||
"color": "#850f0f",
|
"color": "#850f0f",
|
||||||
"values": [
|
"points": [
|
||||||
25000,
|
{
|
||||||
49998,
|
"time": "Year 1",
|
||||||
30000,
|
"value": 25000
|
||||||
100000,
|
},
|
||||||
120000
|
{
|
||||||
|
"time": "Year 2",
|
||||||
|
"value": 49998
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 3",
|
||||||
|
"value": 30000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 4",
|
||||||
|
"value": 100000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 5",
|
||||||
|
"value": 120000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 6",
|
||||||
|
"value": 500000
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "LAMS",
|
"label": "LAMS",
|
||||||
"color": "#a700b3",
|
"color": "#a700b3",
|
||||||
"values": [
|
"points": [
|
||||||
3588,
|
{
|
||||||
7176,
|
"time": "Year 1",
|
||||||
10764,
|
"value": 3588
|
||||||
10000
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 2",
|
||||||
|
"value": 7176
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 3",
|
||||||
|
"value": 10764
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "Year 4",
|
||||||
|
"value": 10000
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -195,7 +226,7 @@
|
|||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"title": "Working Adult GrantWorking Adult GrantWorking Adul",
|
"title": "Working Adult GrantWorking Adult GrantWorking Adul",
|
||||||
"amount": "Up to $1,500Up to $1,500",
|
"amount": "Up to $1,500",
|
||||||
"description": "For students employed full-time while studying.For students employed full-time while studying.For students employed full-time while studying.For students employ"
|
"description": "For students employed full-time while studying.For students employed full-time while studying.For students employed full-time while studying.For students employ"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -114,12 +114,30 @@ module.exports = {
|
|||||||
[
|
[
|
||||||
text("label", "Series label", { maxLength: 40 }),
|
text("label", "Series label", { maxLength: 40 }),
|
||||||
{ key: "color", label: "Series color", type: "color" },
|
{ key: "color", label: "Series color", type: "color" },
|
||||||
stringList("values", "Data points", {
|
objectList(
|
||||||
itemLabel: "Point",
|
"points",
|
||||||
fieldType: "number",
|
"Data points",
|
||||||
min: 0,
|
[
|
||||||
sortable: true,
|
text("time", "Time label", {
|
||||||
|
maxLength: 30,
|
||||||
|
placeholder: "Year 1",
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
key: "value",
|
||||||
|
label: "Value",
|
||||||
|
type: "number",
|
||||||
|
min: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
itemLabel: "Point",
|
||||||
|
sortable: true,
|
||||||
|
itemTitleKey: "time",
|
||||||
|
itemSubtitleKey: "value",
|
||||||
|
helpText: "Each chart point requires both a time label and a numeric value.",
|
||||||
|
emptyText: "No data points yet.",
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
itemLabel: "Series",
|
itemLabel: "Series",
|
||||||
|
|||||||
Reference in New Issue
Block a user