forked from UKSOURCE/cms.lams
- 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
91 lines
4.0 KiB
Plaintext
91 lines
4.0 KiB
Plaintext
<div class="container">
|
|
<div class="d-flex justify-content-between align-items-center mt-4 mb-4 flex-wrap gap-2">
|
|
<div>
|
|
<h1 class="h3 mb-0" style="color: var(--primary-dark);">Programmes Management</h1>
|
|
<p class="text-muted mb-0">Manage all academic programmes displayed on the public website.</p>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<% if (frontendUrl) { %>
|
|
<a href="<%= frontendUrl %>/programmes" class="btn btn-outline-primary" target="_blank" rel="noopener">
|
|
<i class="fas fa-external-link-alt me-2"></i>View Programmes Page
|
|
</a>
|
|
<% } %>
|
|
<a href="/admin/programme/edit/new" class="btn btn-primary shadow-sm">
|
|
<i class="fas fa-plus me-2"></i>Add New Programme
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm border-0 mb-4">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="ps-4" style="width:110px;">ID / Code</th>
|
|
<th>Title</th>
|
|
<th>Level</th>
|
|
<th>Format</th>
|
|
<th>Cost</th>
|
|
<th class="text-center" style="width:80px;">Courses</th>
|
|
<th class="text-center" style="width:80px;">Featured</th>
|
|
<th class="text-end pe-4" style="width:120px;">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% if (data && data.length > 0) { %>
|
|
<% data.forEach(function(item) { %>
|
|
<tr>
|
|
<td class="ps-4">
|
|
<code class="text-primary"><%= item.id %></code>
|
|
</td>
|
|
<td>
|
|
<span class="fw-medium"><%= item.title %></span>
|
|
<% if (item.description) { %>
|
|
<div class="text-muted small text-truncate" style="max-width:280px;"><%= item.description %></div>
|
|
<% } %>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-light text-dark border"><%= item.level || '—' %></span>
|
|
</td>
|
|
<td class="text-muted small"><%= item.format || '—' %></td>
|
|
<td class="text-muted small"><%= item.monthlyCost || item.cost || '—' %></td>
|
|
<td class="text-center">
|
|
<span class="badge bg-secondary rounded-pill"><%= (item.coreCourses || []).length %></span>
|
|
</td>
|
|
<td class="text-center">
|
|
<% if (item.selected) { %>
|
|
<i class="fas fa-star text-warning" title="Featured"></i>
|
|
<% } else { %>
|
|
<i class="far fa-star text-muted" title="Not featured"></i>
|
|
<% } %>
|
|
</td>
|
|
<td class="text-end pe-4">
|
|
<a href="/admin/programme/edit/<%= item._id %>" class="btn btn-sm btn-outline-primary me-1" title="Edit">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
<form action="/admin/programme/delete/<%= item._id %>" method="POST" class="d-inline"
|
|
onsubmit="return confirm('Delete programme \'<%= item.title %>\'? This cannot be undone.');">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger" title="Delete">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<% }); %>
|
|
<% } else { %>
|
|
<tr>
|
|
<td colspan="8" class="text-center text-muted py-5">
|
|
<i class="fas fa-graduation-cap fa-2x mb-3 d-block opacity-25"></i>
|
|
No programmes found.
|
|
<a href="/admin/programme/edit/new" class="d-block mt-2">Add your first programme →</a>
|
|
</td>
|
|
</tr>
|
|
<% } %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|