- db: modules table (name, lessons_count) + entries.module_id (ON DELETE SET NULL), migration + idempotent startup ensure - api: GET /api/modules (public, search + limit/offset, entries_count), POST/PUT/DELETE (admin, audit-logged) - entries: accept/validate module_id on create/update, return module_name, module_id filter - backup/restore: include modules and entries.module_id - student form: required module select, hidden while no modules exist - admin: modules.html + js/modules.js list with pagination, search, create/edit/delete modal - journal: module filter, module select in edit modal, module badge, CSV column
64 lines
2.8 KiB
HTML
64 lines
2.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Темы модулей — Админ-панель</title>
|
|
<link rel="stylesheet" href="admin.css">
|
|
</head>
|
|
<body data-page="modules">
|
|
<div class="layout">
|
|
<div class="sidebar" id="sidebar"></div>
|
|
<div class="main">
|
|
<div class="page-head">
|
|
<h2>Темы модулей</h2>
|
|
<p class="page-sub">Ученик выбирает тему модуля при заполнении формы</p>
|
|
</div>
|
|
|
|
<div class="actions-row" style="margin-bottom:16px">
|
|
<button class="btn-primary" id="addModuleBtn" type="button">
|
|
<span style="font-size:1.2rem">+</span> Добавить модуль
|
|
</button>
|
|
<input type="text" id="moduleSearch" class="search-input" placeholder="Поиск по названию..." style="flex:1;min-width:200px;max-width:340px;padding:10px 14px;font-size:.9rem">
|
|
</div>
|
|
|
|
<div class="list" id="moduleList"><div class="empty">Загрузка…</div></div>
|
|
<div class="pager" id="pager"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-overlay" id="moduleModal">
|
|
<div class="edit-modal" style="max-width:480px">
|
|
<h3 id="moduleModalTitle">Создать модуль</h3>
|
|
<form id="moduleForm" class="settings-stack" style="gap:12px">
|
|
<input type="hidden" id="moduleId">
|
|
<div class="settings-field">
|
|
<label>Название <span style="color:#ef4444">*</span></label>
|
|
<input type="text" name="name" class="settings-input" required placeholder="Например: Основы Python" autocomplete="off">
|
|
</div>
|
|
<div class="settings-field">
|
|
<label>Количество занятий</label>
|
|
<input type="number" name="lessons_count" id="moduleLessons" class="settings-input" min="0" max="10000" step="1" value="0">
|
|
</div>
|
|
<div class="card-foot" style="justify-content:flex-end;gap:8px">
|
|
<button type="button" class="btn-primary ghost" id="moduleCancelBtn">Отмена</button>
|
|
<button type="submit" class="btn-primary" id="moduleSubmitBtn">Создать</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="toast" id="toast"></div>
|
|
<script src="vendor/lucide.min.js"></script>
|
|
<script src="admin.js"></script>
|
|
<script src="js/modules.js"></script>
|
|
<style>
|
|
.page-sub{color:var(--muted);font-size:.85rem;margin:0}
|
|
.module-item{display:flex;justify-content:space-between;align-items:center;gap:12px}
|
|
.module-info{min-width:0;display:flex;flex-direction:column;gap:4px}
|
|
.module-name{font-weight:600;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.module-meta{font-size:.78rem;color:var(--muted)}
|
|
@media (max-width:640px){.module-item{flex-direction:column;align-items:flex-start}}
|
|
</style>
|
|
</body>
|
|
</html> |