Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | 2x 2x 2x 2x 2x 2x 2x 5x 5x 3x 1x 1x 3x 3x 2x 2x 2x 3x 3x 2x 2x 2x 5x 5x 4x 4x 4x 3x 3x 3x 3x 2x 5x 5x 4x 4x 4x 4x 4x 3x 3x 3x 3x 3x 1x 3x 2x 3x 1x 2x 2x 2x 2x 3x 3x 2x 2x 2x 1x 1x 2x | /**
* Fun facts routes — CRUD for language/culture facts shown on splash screen.
*
* GET /api/fun-facts -> All active facts (any authenticated user)
* GET /api/admin/fun-facts -> All facts (admin)
* POST /api/admin/fun-facts -> Create fact (admin)
* PUT /api/admin/fun-facts/:id -> Update fact (admin)
* DELETE /api/admin/fun-facts/:id -> Delete fact (admin)
*/
const router = require('express').Router();
const { db } = require('../utils/firebase');
const { generateId, now } = require('../utils/helpers');
const { requireAdmin } = require('../middleware/auth');
const { queryDocs } = require('../utils/firestore-helpers');
const log = require('../utils/log');
// -- All active facts (any authenticated user) --
router.get('/fun-facts', async (req, res) => {
try {
const results = await queryDocs(db.collection('funFacts').where('isActive', '==', true));
// Shuffle (Firestore has no RANDOM() order)
for (let i = results.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[results[i], results[j]] = [results[j], results[i]];
}
res.set('Cache-Control', 'public, max-age=3600');
return res.json(results);
} catch (err) {
log.error('fun-facts', 'Failed to fetch active fun facts', { error: err.message });
return res.status(500).json({ error: 'Internal server error' });
}
});
// -- All facts (admin) --
router.get('/admin/fun-facts', async (req, res) => {
try {
if (requireAdmin(req, res)) return;
const results = await queryDocs(db.collection('funFacts').orderBy('createdAt', 'desc'));
return res.json(results);
} catch (err) {
log.error('fun-facts', 'Failed to fetch all fun facts', { error: err.message });
return res.status(500).json({ error: 'Internal server error' });
}
});
// -- Create fact (admin) --
router.post('/admin/fun-facts', async (req, res) => {
try {
if (requireAdmin(req, res)) return;
const body = req.body;
Iif (!body) return res.status(400).json({ error: 'Invalid JSON body' });
if (!body.text) return res.status(400).json({ error: 'text is required' });
const id = generateId();
const timestamp = now();
await db.doc(`funFacts/${id}`).set({
id,
text: body.text,
category: body.category || 'trivia',
emoji: body.emoji || '',
sourceLanguage: body.sourceLanguage || body.source_language || '',
isActive: body.isActive === undefined ? body.is_active !== false : !!body.isActive,
createdAt: timestamp,
updatedAt: timestamp,
});
return res.json({ success: true, id });
} catch (err) {
log.error('fun-facts', 'Failed to create fun fact', { error: err.message });
return res.status(500).json({ error: 'Internal server error' });
}
});
// -- Update fact (admin) --
router.put('/admin/fun-facts/:id', async (req, res) => {
try {
if (requireAdmin(req, res)) return;
const body = req.body;
Iif (!body) return res.status(400).json({ error: 'Invalid JSON body' });
const docRef = db.doc(`funFacts/${req.params.id}`);
const snap = await docRef.get();
if (!snap.exists) return res.status(404).json({ error: 'Fun fact not found' });
const fields = {};
if (body.text !== undefined) fields.text = body.text;
Iif (body.category !== undefined) fields.category = body.category;
Iif (body.emoji !== undefined) fields.emoji = body.emoji;
if (body.sourceLanguage !== undefined || body.source_language !== undefined) {
fields.sourceLanguage = body.sourceLanguage ?? body.source_language;
}
if (body.isActive !== undefined || body.is_active !== undefined) {
fields.isActive = !!(body.isActive ?? body.is_active);
}
if (Object.keys(fields).length === 0) {
return res.status(400).json({ error: 'No fields to update' });
}
fields.updatedAt = now();
await docRef.update(fields);
return res.json({ success: true });
} catch (err) {
log.error('fun-facts', 'Failed to update fun fact', {
factId: req.params.id,
error: err.message,
});
return res.status(500).json({ error: 'Internal server error' });
}
});
// -- Delete fact (admin) --
router.delete('/admin/fun-facts/:id', async (req, res) => {
try {
if (requireAdmin(req, res)) return;
const docRef = db.doc(`funFacts/${req.params.id}`);
const snap = await docRef.get();
if (!snap.exists) return res.status(404).json({ error: 'Fun fact not found' });
await docRef.delete();
return res.json({ success: true });
} catch (err) {
log.error('fun-facts', 'Failed to delete fun fact', {
factId: req.params.id,
error: err.message,
});
return res.status(500).json({ error: 'Internal server error' });
}
});
module.exports = router;
|