Feature: Globale Schnellsuche (Cmd/Ctrl+K oder „/")
Keine Sprung-zu-Suche bei wachsender Projekt-/Lead-Zahl. Neuer search-Router (ILIKE ueber Projekte, Leads, offene Blocker) + Command-Palette ueber die Modal-Basis, getriggert per Cmd/Ctrl+K oder „/". Klick springt zum Ziel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
aad247dd4a
commit
a0a2392e3d
4 files changed
+160
No files matched your search
@@ -14,6 +14,7 @@ import { campaignRouter } from './campaign.js';
|
||||
import { areaRouter } from './area.js';
|
||||
import { blockerRouter } from './blocker.js';
|
||||
import { timeRouter } from './time.js';
|
||||
import { searchRouter } from './search.js';
|
||||
|
||||
export const appRouter = router({
|
||||
health: publicProcedure.query(() => ({
|
||||
@@ -34,6 +35,7 @@ export const appRouter = router({
|
||||
dayEntry: dayEntryRouter,
|
||||
time: timeRouter,
|
||||
dashboard: dashboardRouter,
|
||||
search: searchRouter,
|
||||
});
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { z } from 'zod';
|
||||
import { and, ilike, isNull } from 'drizzle-orm';
|
||||
import { project, lead, blocker } from '@cockpit/db';
|
||||
import { router, protectedProcedure } from '../trpc.js';
|
||||
|
||||
/**
|
||||
* Globale Schnellsuche über die wichtigsten Entitäten (Projekte, Leads, offene
|
||||
* Blocker). Postgres ILIKE — für die Teamgröße völlig ausreichend, kein FTS nötig.
|
||||
*/
|
||||
export const searchRouter = router({
|
||||
all: protectedProcedure
|
||||
.input(z.object({ q: z.string().min(1).max(100) }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const term = `%${input.q.replace(/[%_]/g, '\\$&')}%`;
|
||||
const [projects, leads, blockers] = await Promise.all([
|
||||
ctx.db
|
||||
.select({ id: project.id, name: project.name, archiviert: project.archiviert })
|
||||
.from(project)
|
||||
.where(ilike(project.name, term))
|
||||
.limit(8),
|
||||
ctx.db
|
||||
.select({ id: lead.id, firma: lead.firma })
|
||||
.from(lead)
|
||||
.where(ilike(lead.firma, term))
|
||||
.limit(8),
|
||||
ctx.db
|
||||
.select({ id: blocker.id, title: blocker.title })
|
||||
.from(blocker)
|
||||
.where(and(ilike(blocker.title, term), isNull(blocker.resolvedAt)))
|
||||
.limit(8),
|
||||
]);
|
||||
return {
|
||||
projects: projects.map((p) => ({ id: p.id, label: p.name, archived: p.archiviert })),
|
||||
leads: leads.map((l) => ({ id: l.id, label: l.firma })),
|
||||
blockers: blockers.map((b) => ({ id: b.id, label: b.title })),
|
||||
};
|
||||
}),
|
||||
});
|
||||
Reference in new issue
Block a user