Files
cms.techvanguard.vn/utils/contentEditors/admissionsConfig.js
T
Tống Thành Đạt f26b072954 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
2026-04-22 03:48:02 +07:00

232 lines
6.8 KiB
JavaScript

const {
text,
hidden,
textarea,
image,
icon,
checkbox,
object,
stringList,
objectList,
linkFields,
} = require("./sharedFields");
module.exports = {
key: "admissions",
title: "Admissions Management",
subtitle: "Manage the content for the admissions page",
routeBase: "/admin/admissions",
apiPath: "/api/admissions",
previewPath: "/admissions",
dataFile: "admissions",
imageType: "admissions",
tabs: [
{
key: "hero",
label: "Hero",
icon: "fas fa-image",
schema: object("hero", "Hero", [
text("badge", "Eyebrow label", { maxLength: 40 }),
text("title", "Headline", { maxLength: 80 }),
textarea("description", "Supporting text", { maxLength: 240, rows: 4 }),
object("primaryCta", "Primary button", linkFields("Primary button")),
object("secondaryCta", "Secondary button", linkFields("Secondary button")),
image("image", "Hero image", {
imageHint: "Recommended 720x646 px",
helpText: "Large image rendered in the right hero panel.",
}),
text("imageAlt", "Hero image alt text", { maxLength: 120 }),
]),
},
{
key: "process",
label: "Admissions Process",
icon: "fas fa-list-ol",
schema: object("process", "Admissions process", [
text("title", "Section title", { maxLength: 60 }),
textarea("description", "Section description", {
maxLength: 180,
rows: 3,
}),
objectList(
"steps",
"Steps",
[
hidden("number", { autoSequence: { padLength: 2 } }),
text("title", "Step title", { maxLength: 50 }),
textarea("description", "Step description", {
maxLength: 180,
rows: 3,
}),
checkbox("active", "Highlight this step"),
],
{
itemLabel: "Step",
sortable: true,
itemTitleKey: "title",
itemSubtitleKey: "number",
emptyText: "No process steps yet.",
},
),
]),
},
{
key: "eligibility",
label: "Eligibility",
icon: "fas fa-check-circle",
schema: object("eligibility", "Eligibility", [
text("title", "Section title", { maxLength: 60 }),
objectList(
"cards",
"Eligibility cards",
[
text("title", "Card title", { maxLength: 50 }),
icon("icon", "Card icon"),
stringList("items", "Checklist items", {
itemLabel: "Checklist item",
maxLength: 120,
sortable: true,
}),
],
{
itemLabel: "Card",
sortable: true,
itemTitleKey: "title",
emptyText: "No eligibility cards yet.",
},
),
]),
},
{
key: "tuition",
label: "Tuition",
icon: "fas fa-chart-column",
schema: object("tuition", "Tuition", [
text("title", "Section title", { maxLength: 60 }),
text("chartTitle", "Chart title", { maxLength: 60 }),
textarea("chartDescription", "Chart description", {
maxLength: 140,
rows: 3,
}),
objectList(
"series",
"Chart series",
[
text("label", "Series label", { maxLength: 40 }),
{ key: "color", label: "Series color", type: "color" },
objectList(
"points",
"Data points",
[
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",
sortable: true,
itemTitleKey: "label",
emptyText: "No chart series yet.",
},
),
]),
},
{
key: "keyDates",
label: "Key Dates",
icon: "fas fa-calendar-days",
schema: object("keyDates", "Key dates", [
text("title", "Section title", { maxLength: 60 }),
]),
},
{
key: "calculator",
label: "Calculator",
icon: "fas fa-calculator",
schema: object("calculator", "Calculator", [
text("title", "Card title", { maxLength: 60 }),
textarea("description", "Card description", {
maxLength: 120,
rows: 3,
}),
object("cta", "Button", linkFields("Button")),
objectList(
"options",
"Calculator options",
[
hidden("id"),
text("label", "Option label", { maxLength: 12 }),
text("paceLabel", "Pace label", { maxLength: 30 }),
text("minPaceLabel", "Minimum pace label", { maxLength: 20 }),
text("maxPaceLabel", "Maximum pace label", { maxLength: 20 }),
text("resultLabel", "Result label", { maxLength: 40 }),
text("monthlyAmount", "Monthly amount", { maxLength: 20 }),
text("monthlySuffix", "Monthly suffix", { maxLength: 10 }),
icon("noteIcon", "Note icon"),
text("note", "Note text", { maxLength: 60 }),
],
{
itemLabel: "Option",
sortable: true,
itemTitleKey: "label",
emptyText: "No calculator options yet.",
itemActions: [
{
label: "Edit option",
icon: "fas fa-pen",
className: "btn btn-outline-primary btn-sm",
hrefTemplate: "/admin/admissions/calculator/{id}",
},
],
},
),
]),
},
{
key: "scholarships",
label: "Scholarships",
icon: "fas fa-award",
schema: object("scholarships", "Scholarships", [
text("title", "Card title", { maxLength: 50 }),
icon("icon", "Card icon"),
objectList(
"items",
"Scholarship items",
[
text("title", "Title", { maxLength: 50 }),
text("amount", "Amount", { maxLength: 24 }),
textarea("description", "Description", {
maxLength: 160,
rows: 3,
}),
],
{
itemLabel: "Scholarship item",
sortable: true,
itemTitleKey: "title",
itemSubtitleKey: "amount",
emptyText: "No scholarship items yet.",
},
),
]),
},
],
};