feat: add programme module and blog integration

- Add Programme Mongoose model with sub-schemas and migrateFromJson static method
- Add programme CRUD controller with audit logging and icon sanitization
- Add programme admin views (index, edit) with tabbed form and dynamic arrays
- Add seed migration script for programmes
- Add /api/programmes and /api/programmes/:id public API endpoints
- Register programme routes in admin and public router
- Update dashboard with Programmes card and API endpoint entries
- Update admin sidebar layout to include Programmes nav link
This commit is contained in:
2026-04-20 18:40:29 +07:00
parent ac5fa14c97
commit 30b90051c9
12 changed files with 1311 additions and 2 deletions
+63 -2
View File
@@ -234,6 +234,25 @@
</a>
</div>
</div>
<!-- Programme -->
<div class="col-md-4 border-top">
<div class="p-4">
<div class="d-flex align-items-center mb-3">
<div class="rounded-circle d-flex align-items-center justify-content-center me-3"
style="width: 50px; height: 50px; background-color: rgba(184, 183, 106, 0.1);">
<i class="fas fa-graduation-cap fa-lg" style="color: var(--primary-color);"></i>
</div>
<div>
<h5 class="mb-0">Programmes</h5>
<p class="text-muted mb-0 small">Manage academic programmes</p>
</div>
</div>
<a href="/admin/programme" class="btn btn-sm btn-primary w-100 mt-2">
<i class="fas fa-edit me-2"></i>Manage
</a>
</div>
</div>
</div>
</div>
</div>
@@ -242,7 +261,7 @@
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">API Endpoints</h5>
<span class="badge bg-primary">7 APIs</span>
<span class="badge bg-primary">9 APIs</span>
</div>
<div class="card-body p-0">
<div class="table-responsive">
@@ -421,13 +440,55 @@
<td>
<span class="badge" style="background-color: var(--primary-color)">GET</span>
</td>
<td>API to get blog posts</td>
<td>List published blog posts (supports ?page, ?category, ?search)</td>
<td>
<a href="/api/blog" class="btn btn-sm btn-outline-primary" target="_blank">
<i class="fas fa-external-link-alt me-1"></i>View
</a>
</td>
</tr>
<tr>
<td>
<div class="d-flex align-items-center">
<div class="rounded-circle d-flex align-items-center justify-content-center me-2"
style="width: 32px; height: 32px; background-color: rgba(184, 183, 106, 0.1);">
<i class="fas fa-graduation-cap" style="color: var(--primary-color);"></i>
</div>
<span>Programmes API</span>
</div>
</td>
<td><code>/api/programmes</code></td>
<td>
<span class="badge" style="background-color: var(--primary-color)">GET</span>
</td>
<td>List all academic programmes</td>
<td>
<a href="/api/programmes" class="btn btn-sm btn-outline-primary" target="_blank">
<i class="fas fa-external-link-alt me-1"></i>View
</a>
</td>
</tr>
<tr>
<td>
<div class="d-flex align-items-center">
<div class="rounded-circle d-flex align-items-center justify-content-center me-2"
style="width: 32px; height: 32px; background-color: rgba(184, 183, 106, 0.1);">
<i class="fas fa-graduation-cap" style="color: var(--primary-color);"></i>
</div>
<span>Programme Detail API</span>
</div>
</td>
<td><code>/api/programmes/:id</code></td>
<td>
<span class="badge" style="background-color: var(--primary-color)">GET</span>
</td>
<td>Single programme by slug ID</td>
<td>
<a href="/api/programmes" class="btn btn-sm btn-outline-primary" target="_blank">
<i class="fas fa-external-link-alt me-1"></i>View
</a>
</td>
</tr>
</tbody>
</table>
</div>