feat: Feed-Pagination – erledigte und vom Client gelieferte Pairs ausschließen
GET /auth/feed schließt jetzt Pairs aus user_pair_progress (cross-session) sowie per ?exclude=<uuids> übergebene, bereits geladene Pairs (In-Session) aus. Leere Antwort signalisiert dem Client: keine weiteren Karten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -41,10 +41,18 @@ router.get('/', requireJwt, async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
const lang = ['de', 'en', 'sv'].includes(req.query.lang) ? req.query.lang : 'de';
|
const lang = ['de', 'en', 'sv'].includes(req.query.lang) ? req.query.lang : 'de';
|
||||||
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
|
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
|
||||||
|
const userId = req.user.userId;
|
||||||
|
// Vom Client schon geladene Pairs (In-Session-Dedupe) – nur gültige UUIDs übernehmen.
|
||||||
|
const exclude = String(req.query.exclude || '')
|
||||||
|
.split(',')
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(s => /^[0-9a-f-]{36}$/i.test(s));
|
||||||
|
|
||||||
// 1. Random pairs — only fully ready content:
|
// 1. Random pairs — only fully ready content:
|
||||||
// pair published + linked question/statements published + a published picture exists.
|
// pair published + linked question/statements published + a published picture exists.
|
||||||
// (Audio coverage is additionally enforced in Phase 2.)
|
// (Audio coverage is additionally enforced in Phase 2.)
|
||||||
|
// Pagination: bereits abgeschlossene (user_pair_progress) und vom Client
|
||||||
|
// geladene Pairs werden ausgeschlossen; leere Antwort = keine weiteren Karten.
|
||||||
const pairsRes = await query(
|
const pairsRes = await query(
|
||||||
`SELECT p.id, p.answer_type, p.status, p.difficulty_level,
|
`SELECT p.id, p.answer_type, p.status, p.difficulty_level,
|
||||||
p.question_id, p.positive_statement_id, p.negative_statement_id
|
p.question_id, p.positive_statement_id, p.negative_statement_id
|
||||||
@@ -61,9 +69,13 @@ router.get('/', requireJwt, async (req, res, next) => {
|
|||||||
JOIN object_pictures pic ON pic.object_id = op.object_id
|
JOIN object_pictures pic ON pic.object_id = op.object_id
|
||||||
JOIN pictures pp ON pp.id = pic.picture_id
|
JOIN pictures pp ON pp.id = pic.picture_id
|
||||||
WHERE op.pair_id = p.id AND pp.status = 'published')
|
WHERE op.pair_id = p.id AND pp.status = 'published')
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM user_pair_progress upp
|
||||||
|
WHERE upp.pair_id = p.id AND upp.user_id = $2)
|
||||||
|
AND p.id <> ALL($3::uuid[])
|
||||||
ORDER BY random()
|
ORDER BY random()
|
||||||
LIMIT $1`,
|
LIMIT $1`,
|
||||||
[limit]
|
[limit, userId, exclude]
|
||||||
);
|
);
|
||||||
if (!pairsRes.rows.length) return res.json([]);
|
if (!pairsRes.rows.length) return res.json([]);
|
||||||
const pairs = pairsRes.rows;
|
const pairs = pairsRes.rows;
|
||||||
|
|||||||
Reference in New Issue
Block a user