diff --git a/backend/src/controllers/courseController.js b/backend/src/controllers/courseController.js
index 79ad37d..974ce88 100644
--- a/backend/src/controllers/courseController.js
+++ b/backend/src/controllers/courseController.js
@@ -45,6 +45,10 @@ function list(req, res) {
let where = role === 'student' ? 'WHERE c.is_published = 1' : 'WHERE 1=1';
const args = [];
if (subject) { where += ' AND c.subject_slug = ?'; args.push(subject); }
+ // Personal "container" courses (quick lessons) are hidden from the catalog;
+ // their owner still sees their own.
+ if (role === 'student') { where += ' AND c.is_personal = 0'; }
+ else { where += ' AND (c.is_personal = 0 OR c.created_by = ?)'; args.push(uid); }
const rows = db.prepare(`
SELECT c.*,
diff --git a/backend/src/controllers/lessonController.js b/backend/src/controllers/lessonController.js
index a3ead48..7e404af 100644
--- a/backend/src/controllers/lessonController.js
+++ b/backend/src/controllers/lessonController.js
@@ -302,4 +302,28 @@ function deleteComment(req, res) {
res.json({ ok: true });
}
-module.exports = { get, create, update, remove, saveBlocks, markComplete, saveNote, listComments, addComment, deleteComment };
+/* ── POST /api/lessons/quick ──────────────────────────────────────────────
+ Create a standalone "quick lesson" without manually building a course:
+ reuse (or lazily create) the teacher's hidden personal container course,
+ add one lesson to it, and return its id for the editor. */
+function quickLesson(req, res) {
+ const uid = req.user.id;
+ let container = db.prepare(
+ 'SELECT id FROM courses WHERE created_by = ? AND is_personal = 1 ORDER BY id LIMIT 1'
+ ).get(uid);
+ if (!container) {
+ const r = db.prepare(`
+ INSERT INTO courses (subject_slug, title, description, cover_emoji, order_index, is_published, is_personal, created_by)
+ VALUES ('personal', 'Мои материалы', 'Отдельные уроки без курса', '', 0, 1, 1, ?)
+ `).run(uid);
+ container = { id: Number(r.lastInsertRowid) };
+ }
+ const title = (req.body && req.body.title && String(req.body.title).trim()) || 'Новый урок';
+ const n = db.prepare('SELECT COUNT(*) AS c FROM lessons WHERE course_id = ?').get(container.id).c;
+ const r2 = db.prepare(
+ 'INSERT INTO lessons (course_id, title, order_index) VALUES (?, ?, ?)'
+ ).run(container.id, title, n);
+ res.status(201).json({ lessonId: Number(r2.lastInsertRowid), courseId: container.id });
+}
+
+module.exports = { get, create, update, remove, saveBlocks, markComplete, saveNote, listComments, addComment, deleteComment, quickLesson };
diff --git a/backend/src/db/migrations/059_courses_personal.sql b/backend/src/db/migrations/059_courses_personal.sql
new file mode 100644
index 0000000..8394626
--- /dev/null
+++ b/backend/src/db/migrations/059_courses_personal.sql
@@ -0,0 +1,11 @@
+-- ═══════════════════════════════════════════════════════════════
+-- 059: Personal "container" course for standalone quick lessons
+--
+-- A teacher who just wants to author a single lesson (without manually
+-- creating a whole course) gets a hidden personal container course
+-- (is_personal = 1, one per teacher). Quick lessons are added there.
+-- The course catalog hides personal containers from everyone except their
+-- owner (see courseController.list).
+-- ═══════════════════════════════════════════════════════════════
+
+ALTER TABLE courses ADD COLUMN is_personal INTEGER NOT NULL DEFAULT 0;
diff --git a/backend/src/routes/lessons.js b/backend/src/routes/lessons.js
index 5ea0f58..602d771 100644
--- a/backend/src/routes/lessons.js
+++ b/backend/src/routes/lessons.js
@@ -13,6 +13,7 @@ router.post('/:id/comments', c.addComment);
router.delete('/:id/comments/:cid', c.deleteComment);
// Teacher/admin only
+router.post('/quick', requireRole('teacher','admin'), c.quickLesson);
router.post('/', requireRole('teacher','admin'), c.create);
router.put('/:id', requireRole('teacher','admin'), c.update);
router.delete('/:id', requireRole('teacher','admin'), c.remove);
diff --git a/frontend/theory.html b/frontend/theory.html
index d933c31..ec609d4 100644
--- a/frontend/theory.html
+++ b/frontend/theory.html
@@ -304,6 +304,9 @@
+
@@ -350,6 +353,7 @@
document.getElementById('btn-classes').style.display = '';
document.getElementById('btn-new-course').style.display = '';
document.getElementById('btn-from-tpl').style.display = '';
+ document.getElementById('btn-quick-lesson').style.display = '';
}
if (isAdmin) {
document.getElementById('btn-admin').style.display = '';
@@ -586,6 +590,24 @@
}
}
+ /* Быстрый урок: создаёт отдельный урок в личном курсе-контейнере и сразу
+ открывает редактор — без ручного создания курса. */
+ async function createQuickLesson() {
+ const btn = document.getElementById('btn-quick-lesson');
+ if (btn) btn.disabled = true;
+ try {
+ const res = await LS.api('/api/lessons/quick', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({}),
+ });
+ location.href = '/lesson-editor.html?id=' + res.lessonId;
+ } catch (e) {
+ LS.toast(e.message || 'Ошибка', 'error');
+ if (btn) btn.disabled = false;
+ }
+ }
+
/* ══════════════════════════════════════════════════════════════════
TEMPLATE BROWSER
══════════════════════════════════════════════════════════════════ */