const path = require('path'); const fs = require('fs'); let db; function init(database) { db = database; } function getUploadsDir() { const dir = path.join(__dirname, '..', '..', 'data', 'activity_images'); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); return dir; } function validLangCount(row) { let count = 0; if (row.title_ru || row.desc_ru) count++; if (row.title_en || row.desc_en) count++; if (row.title_ab || row.desc_ab) count++; return count; } function pickLang(row, lang) { const filled = validLangCount(row); if (filled === 1) { if (row.title_ru || row.desc_ru) return { title: row.title_ru, desc: row.desc_ru }; if (row.title_en || row.desc_en) return { title: row.title_en, desc: row.desc_en }; return { title: row.title_ab, desc: row.desc_ab }; } return { title: row['title_' + lang] || row.title_ru || '', desc: row['desc_' + lang] || row.desc_ru || '' }; } function getPublicActivities(req, res) { const lang = req.query.lang || 'ru'; db.all( `SELECT id, title_ru, title_en, title_ab, desc_ru, desc_en, desc_ab, icon, image_path FROM activities WHERE is_active = 1 ORDER BY sort_order ASC, id ASC`, [], (err, rows) => { if (err) { console.error('Get activities error:', err); return res.status(500).json({ error: 'Database error' }); } const activities = rows.map(row => { const localized = pickLang(row, lang); return { id: row.id, title: localized.title, desc: localized.desc, icon: row.icon, image_path: row.image_path }; }); res.json(activities); } ); } function getAdminActivities(req, res) { db.all( `SELECT * FROM activities ORDER BY sort_order ASC, id ASC`, [], (err, rows) => { if (err) { console.error('Get admin activities error:', err); return res.status(500).json({ error: 'Database error' }); } rows.forEach(row => { row.created_at = row.created_at ? new Date(row.created_at).toISOString() : null; }); res.json(rows); } ); } function createActivity(req, res) { const { title_ru, title_en, title_ab, desc_ru, desc_en, desc_ab, icon, image_path, sort_order } = req.body; const rawRow = { title_ru, title_en, title_ab, desc_ru, desc_en, desc_ab }; const count = validLangCount(rawRow); if (count !== 1 && count !== 3) { return res.status(400).json({ error: 'Должен быть заполнен 1 язык или все 3' }); } db.run( `INSERT INTO activities (title_ru, title_en, title_ab, desc_ru, desc_en, desc_ab, icon, image_path, sort_order, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)`, [title_ru || null, title_en || null, title_ab || null, desc_ru || null, desc_en || null, desc_ab || null, icon || null, image_path || null, sort_order || 0], function(err) { if (err) { console.error('Create activity error:', err); return res.status(500).json({ error: 'Database error' }); } res.status(201).json({ message: 'Activity created', id: this.lastID }); } ); } function updateActivity(req, res) { const id = parseInt(req.params.id); const langFields = ['title_ru', 'title_en', 'title_ab', 'desc_ru', 'desc_en', 'desc_ab']; const anyLangChanged = langFields.some(f => req.body[f] !== undefined); if (anyLangChanged) { const rawRow = {}; langFields.forEach(f => { rawRow[f] = req.body[f]; }); const count = validLangCount(rawRow); if (count !== 0 && count !== 1 && count !== 3) { return res.status(400).json({ error: 'Должен быть заполнен 1 язык или все 3' }); } } const allowed = ['title_ru', 'title_en', 'title_ab', 'desc_ru', 'desc_en', 'desc_ab', 'icon', 'image_path', 'sort_order', 'is_active']; const fields = []; const values = []; allowed.forEach(f => { if (req.body[f] !== undefined) { fields.push(f + ' = ?'); values.push(req.body[f] === '' ? null : req.body[f]); } }); if (!fields.length) { return res.status(400).json({ error: 'No fields to update' }); } values.push(id); db.run( `UPDATE activities SET ${fields.join(', ')} WHERE id = ?`, values, function(err) { if (err) { console.error('Update activity error:', err); return res.status(500).json({ error: 'Database error' }); } if (this.changes === 0) { return res.status(404).json({ error: 'Activity not found' }); } res.json({ message: 'Activity updated', id }); } ); } function deleteActivity(req, res) { const id = parseInt(req.params.id); db.run(`DELETE FROM activities WHERE id = ?`, [id], function(err) { if (err) { console.error('Delete activity error:', err); return res.status(500).json({ error: 'Database error' }); } if (this.changes === 0) { return res.status(404).json({ error: 'Activity not found' }); } res.json({ message: 'Activity deleted', id }); }); } function uploadActivityImage(req, res) { if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } const filename = req.file.filename; const activityId = parseInt(req.params.id); const imagePath = 'data/activity_images/' + filename; if (activityId && req.body.update_activity === '1') { db.run(`UPDATE activities SET image_path = ? WHERE id = ?`, [imagePath, activityId], function(err) { if (err) { console.error('Update activity image error:', err); return res.status(500).json({ error: 'Database error' }); } }); } res.json({ message: 'Image uploaded', path: imagePath, filename }); } function getAllActivities(req, res) { getAdminActivities(req, res); } function setupRoutes(app, authenticateToken, requireAdmin, upload) { app.get('/api/activities', getPublicActivities); app.get('/api/admin/activities', authenticateToken, getAllActivities); app.post('/api/admin/activities', authenticateToken, createActivity); app.put('/api/admin/activities/:id', authenticateToken, updateActivity); app.delete('/api/admin/activities/:id', authenticateToken, deleteActivity); app.post('/api/admin/activities/upload', authenticateToken, upload.single('image'), uploadActivityImage); app.post('/api/admin/activities/:id/image', authenticateToken, upload.single('image'), uploadActivityImage); } module.exports = { init, setupRoutes, getUploadsDir };