ci: dev version includes UTC time (dev-YYYYMMDD-HHmm)
Build & Push Docker Image / build (push) Successful in 2m36s
Build & Push Docker Image / build (push) Successful in 2m36s
Phase 1: browse power-up - faceted filters: tags + features (array containment) and min rating on listTools; new ?tags=?features=?minRating= URL params with chips - global Cmd+K command palette (cmdk) with tool search + navigation - mini usefulness/usability bars on grid cards, wide cards and table rows
This commit is contained in:
@@ -52,7 +52,10 @@ router.get("/tools", async (req, res): Promise<void> => {
|
||||
res.status(400).json({ error: parsed.error.message });
|
||||
return;
|
||||
}
|
||||
const { category, search, sort } = parsed.data;
|
||||
const { category, search, sort, tags, features, minRating } = parsed.data;
|
||||
|
||||
const tagList = (tags ?? "").split(",").map((t) => t.trim()).filter(Boolean);
|
||||
const featureList = (features ?? "").split(",").map((f) => f.trim()).filter(Boolean);
|
||||
|
||||
let query = db.select().from(toolsTable).where(isNull(toolsTable.deletedAt)).$dynamic();
|
||||
if (category) {
|
||||
@@ -62,6 +65,12 @@ router.get("/tools", async (req, res): Promise<void> => {
|
||||
const escaped = search.replace(/[%_\\]/g, (m) => `\\${m}`);
|
||||
query = query.where(sql`${toolsTable.name} ilike ${`%${escaped}%`} escape '\\'`);
|
||||
}
|
||||
if (tagList.length > 0) {
|
||||
query = query.where(sql`${toolsTable.tags} @> ARRAY[${sql.join(tagList.map((t) => sql`${t}`), sql`, `)}]::text[]`);
|
||||
}
|
||||
if (featureList.length > 0) {
|
||||
query = query.where(sql`${toolsTable.features} @> ARRAY[${sql.join(featureList.map((f) => sql`${f}`), sql`, `)}]::text[]`);
|
||||
}
|
||||
|
||||
const tools = await query.orderBy(desc(toolsTable.createdAt));
|
||||
|
||||
@@ -95,6 +104,10 @@ router.get("/tools", async (req, res): Promise<void> => {
|
||||
result = result.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
||||
}
|
||||
|
||||
if (minRating != null) {
|
||||
result = result.filter((t) => (t.avgCombined ?? 0) >= minRating);
|
||||
}
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user