Add ?search= server-side ILIKE filter to words, pictures, categories

- words: ILIKE across titel_de, titel_en, titel_sv
- pictures: ILIKE on design
- categories: ILIKE across name_de, name_en, name_sv

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 22:50:38 +02:00
parent 6d1f610e3d
commit cea19083b4
3 changed files with 20 additions and 7 deletions

View File

@@ -12,10 +12,16 @@ const STATUS_TIMESTAMP = {
// GET /api/categories
router.get('/', async (req, res, next) => {
try {
const { status, limit = 50, offset = 0 } = req.query;
const { status, search, limit = 50, offset = 0 } = req.query;
const params = [Math.min(parseInt(limit), 500), parseInt(offset)];
const where = status ? `WHERE c.status = $3` : '';
if (status) params.push(status);
const conditions = [];
if (status) { conditions.push(`c.status = $${params.length + 1}`); params.push(status); }
if (search) {
const p = `%${search.toLowerCase()}%`;
conditions.push(`(lower(c.name_de) LIKE $${params.length + 1} OR lower(c.name_en) LIKE $${params.length + 1} OR lower(c.name_sv) LIKE $${params.length + 1})`);
params.push(p);
}
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
const result = await query(
`SELECT c.*,
COALESCE(json_agg(DISTINCT w.id) FILTER (WHERE w.id IS NOT NULL), '[]') AS word_ids

View File

@@ -12,10 +12,12 @@ const ALLOWED_BLOCKED_REASONS = ['regenerate', 'not_to_use'];
// GET /api/pictures
router.get('/', async (req, res, next) => {
try {
const { status, limit = 50, offset = 0 } = req.query;
const { status, search, limit = 50, offset = 0 } = req.query;
const params = [Math.min(parseInt(limit), 500), parseInt(offset)];
const where = status ? `WHERE status = $3` : '';
if (status) params.push(status);
const conditions = [];
if (status) { conditions.push(`status = $${params.length + 1}`); params.push(status); }
if (search) { conditions.push(`lower(design) LIKE $${params.length + 1}`); params.push(`%${search.toLowerCase()}%`); }
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
const result = await query(
`SELECT * FROM pictures ${where} ORDER BY created_at DESC LIMIT $1 OFFSET $2`,
params

View File

@@ -12,11 +12,16 @@ const STATUS_TIMESTAMP = {
// GET /api/words
router.get('/', async (req, res, next) => {
try {
const { status, titel_de, limit = 50, offset = 0 } = req.query;
const { status, titel_de, search, limit = 50, offset = 0 } = req.query;
const params = [Math.min(parseInt(limit), 500), parseInt(offset)];
const conditions = [];
if (status) { conditions.push(`w.status = $${params.length + 1}`); params.push(status); }
if (titel_de) { conditions.push(`lower(w.titel_de) = lower($${params.length + 1})`); params.push(titel_de); }
if (search) {
const p = `%${search.toLowerCase()}%`;
conditions.push(`(lower(w.titel_de) LIKE $${params.length + 1} OR lower(w.titel_en) LIKE $${params.length + 1} OR lower(w.titel_sv) LIKE $${params.length + 1})`);
params.push(p);
}
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
const result = await query(
`SELECT w.*,