feat(cms): enhance content editors with dynamic UI configs and validation

Implement a more flexible, configuration-driven approach for CMS editors across accreditation, admissions, and partnerships modules.
- Move UI labels, help texts, and field limits from hardcoded views to `editorUi` configurations in config files.
- Add server-side and client-side validation to prevent duplicate category tabs in accreditation and partnerships editors.
- Refactor partnership and admission views to dynamically render tabs and fields based on the provided configuration.
- Update field length constraints and default values across multiple content editors to better align with frontend requirements.
- Improve the admissions calculator editor with dynamic field configurations and default value fallbacks.
This commit is contained in:
Tống Thành Đạt
2026-04-22 18:06:03 +07:00
parent a44d005c13
commit a39c336dd4
19 changed files with 790 additions and 228 deletions
+14 -25
View File
@@ -20,34 +20,21 @@
<div class="card shadow-sm border-0 mb-4">
<div class="card-header bg-white border-bottom">
<ul class="nav nav-tabs card-header-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link <%= activeTab === 'hero' ? 'active' : '' %>" data-bs-toggle="tab" href="#hero" role="tab" data-tab-key="hero">
<i class="fas fa-image me-2"></i>Hero
</a>
</li>
<li class="nav-item">
<a class="nav-link <%= activeTab === 'directory' ? 'active' : '' %>" data-bs-toggle="tab" href="#directory" role="tab" data-tab-key="directory">
<i class="fas fa-handshake me-2"></i>Partner Directory
</a>
</li>
<li class="nav-item">
<a class="nav-link <%= activeTab === 'cta' ? 'active' : '' %>" data-bs-toggle="tab" href="#cta" role="tab" data-tab-key="cta">
<i class="fas fa-bullhorn me-2"></i>Call To Action
</a>
</li>
<li class="nav-item">
<a class="nav-link <%= activeTab === 'inquiryForm' ? 'active' : '' %>" data-bs-toggle="tab" href="#inquiryForm" role="tab" data-tab-key="inquiryForm">
<i class="fas fa-envelope me-2"></i>Inquiry Form
</a>
</li>
<% editorConfig.tabs.forEach((tab) => { %>
<li class="nav-item">
<a class="nav-link <%= activeTab === tab.key ? 'active' : '' %>" data-bs-toggle="tab" href="#<%= tab.key %>" role="tab" data-tab-key="<%= tab.key %>">
<i class="<%= tab.icon %> me-2"></i><%= tab.label %>
</a>
</li>
<% }) %>
</ul>
</div>
<div class="tab-content">
<%- include("partials/hero-tab", { activeTab, data, backendUrl }) %>
<%- include("partials/directory-tab", { activeTab, data }) %>
<%- include("partials/cta-tab", { activeTab, data }) %>
<%- include("partials/inquiry-form-tab", { activeTab, data }) %>
<%- include("partials/hero-tab", { activeTab, data, backendUrl, editorUi }) %>
<%- include("partials/directory-tab", { activeTab, data, editorUi }) %>
<%- include("partials/cta-tab", { activeTab, data, editorUi }) %>
<%- include("partials/inquiry-form-tab", { activeTab, data, editorUi }) %>
</div>
</div>
@@ -66,11 +53,13 @@
</div>
</div>
<%- include("partials/templates") %>
<%- include("partials/templates", { editorUi }) %>
<script>
window.partnershipsPageData = <%- JSON.stringify(data) %>;
window.partnershipsBackendUrl = <%- JSON.stringify(backendUrl) %>;
window.partnershipsEditorConfig = <%- JSON.stringify(editorConfig) %>;
window.partnershipsEditorUi = <%- JSON.stringify(editorUi) %>;
</script>
<%- include("partials/editor-script") %>