const express = require('express'); const router = express.Router(); const sentencesController = require('../controllers/sentencesController'); const { authenticateToken } = require('../middleware/auth'); /** * ============================================ * POST /api/sentences * ============================================ * Tạo một sentence entry mới * * INPUT: * { * text: String (required) - nội dung câu * ipa: String - phiên âm IPA * vi: String - nghĩa tiếng Việt * category: String - category của câu * topic: String - chủ đề * image_small: JSON Array - mảng URLs hình ảnh nhỏ * image_square: JSON Array - mảng URLs hình ảnh vuông * image_normal: JSON Array - mảng URLs hình ảnh bình thường * audio: JSON Array - mảng URLs audio files * tags: JSON Array - các tags phân loại * usage_note: String - lưu ý ngữ cảnh sử dụng * etc: String - các thông tin khác * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Sentence object đã tạo (bao gồm id, created_at, updated_at) * } **/ router.post('/', sentencesController.createSentence); /** * ============================================ * POST /api/sentences/bulk * ============================================ * Tạo nhiều sentence entries cùng lúc * * INPUT: * { * sentences: Array of Sentence objects - mỗi object phải có text * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of created Sentence objects, * count: Number - số lượng đã tạo * } **/ router.post('/bulk', sentencesController.bulkCreateSentences); /** * ============================================ * POST /api/sentences/search * ============================================ * Tìm kiếm sentence nâng cao với nhiều filter * * INPUT: * { * topic: String (optional) * category: String (optional) * text: String (optional) - partial match * vi: String (optional) - partial match * page: Number (mặc định: 1) * limit: Number (mặc định: 100) * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of Sentence objects, * pagination: { total, page, limit, totalPages } * } **/ router.post('/search', sentencesController.searchSentences); /** * ============================================ * GET /api/sentences * ============================================ * Lấy danh sách tất cả sentences với phân trang và filter * * INPUT (Query Parameters): * { * page: Number (mặc định: 1) * limit: Number (mặc định: 20) * category: String * topic: String * text: String * search: String - tìm kiếm trong text và vi * is_active: Boolean (mặc định: true) * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of Sentence objects, * pagination: { total, page, limit, totalPages } * } **/ router.get('/', sentencesController.getAllSentences); /** * ============================================ * GET /api/sentences/stats/overview * ============================================ * Lấy thống kê tổng quan về sentences * * OUTPUT: * { * success: Boolean, * message: String, * data: { * total: { active, inactive, all }, * by_category: Array [{category, count}], * by_topic: Array [{topic, count}] * } * } **/ router.get('/stats/overview', sentencesController.getSentenceStats); /** * ============================================ * GET /api/sentences/meta/categories * ============================================ * Lấy danh sách tất cả categories * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of String, * count: Number * } **/ router.get('/meta/categories', sentencesController.getAllCategories); /** * ============================================ * GET /api/sentences/meta/topics * ============================================ * Lấy danh sách tất cả topics * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of String, * count: Number * } **/ router.get('/meta/topics', sentencesController.getAllTopics); /** * ============================================ * GET /api/sentences/missing/ipa * ============================================ * Lấy tất cả sentences chưa có IPA * * INPUT (Query Parameters): * { * page: Number (mặc định: 1) * limit: Number (mặc định: 50) * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of Sentence objects, * pagination: { total, page, limit, totalPages } * } **/ router.get('/missing/ipa', sentencesController.getSentencesWithoutIpa); /** * ============================================ * GET /api/sentences/missing/images * ============================================ * Lấy tất cả sentences chưa đủ hình ảnh * * INPUT (Query Parameters): * { * page: Number (mặc định: 1) * limit: Number (mặc định: 50) * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Array of Sentence objects, * pagination: { total, page, limit, totalPages } * } **/ router.get('/missing/images', sentencesController.getSentencesWithoutImages); /** * ============================================ * GET /api/sentences/:id * ============================================ * Lấy chi tiết một sentence theo ID * * INPUT (URL Parameter): * { * id: UUID - id của sentence cần lấy * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Sentence object * } **/ router.get('/:id', sentencesController.getSentenceById); /** * ============================================ * PUT /api/sentences/:id * ============================================ * Cập nhật thông tin sentence * * INPUT (URL Parameter + Body): * { * id: UUID - id cần update * Body: Object - các trường cần update * { * text, ipa, vi, category, topic, * image_small, image_square, image_normal, * audio, tags, usage_note, etc, is_active * } * } * * OUTPUT: * { * success: Boolean, * message: String, * data: Updated Sentence object * } **/ router.put('/:id', sentencesController.updateSentence); /** * ============================================ * DELETE /api/sentences/:id * ============================================ * Xóa mềm sentence (set is_active = false) * * INPUT (URL Parameter): * { * id: UUID - id cần xóa * } * * OUTPUT: * { * success: Boolean, * message: String * } **/ router.delete('/:id', sentencesController.deleteSentence); module.exports = router;