From 04d415f2ccbbfca1def69cc3bfa2a922ce353fe5 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Sun, 13 Jul 2025 23:07:28 +0200 Subject: [PATCH] feat(sessions): add missing language, sortKey, and sortOrder filtering support - Add language field with ISO 639-1 validation to sessionFilterSchema - Add sortKey enum with startTime, category, language, sentiment, sessionId options - Add sortOrder enum with asc/desc options - Update tRPC router to support new filtering and sorting parameters - Uncomment frontend code to enable full filtering functionality - Add comprehensive validation tests for new schema fields Resolves commented out filter options in app/dashboard/sessions/page.tsx lines 491-502 --- app/dashboard/sessions/page.tsx | 6 +++--- lib/validation.ts | 8 ++++++++ server/routers/dashboard.ts | 20 +++++++++++++++++--- tests/unit/validation.test.ts | 30 ++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/app/dashboard/sessions/page.tsx b/app/dashboard/sessions/page.tsx index 97d5b57..73d09c6 100644 --- a/app/dashboard/sessions/page.tsx +++ b/app/dashboard/sessions/page.tsx @@ -504,11 +504,11 @@ export default function SessionsPage() { category: selectedCategory ? (selectedCategory as z.infer["category"]) : undefined, - // language: selectedLanguage || undefined, // Not supported in schema yet + language: selectedLanguage || undefined, startDate: startDate || undefined, endDate: endDate || undefined, - // sortKey: sortKey || undefined, // Not supported in schema yet - // sortOrder: sortOrder || undefined, // Not supported in schema yet + sortKey: sortKey || undefined, + sortOrder: sortOrder || undefined, page: currentPage, limit: pageSize, }, diff --git a/lib/validation.ts b/lib/validation.ts index b4189bb..59a2dbb 100644 --- a/lib/validation.ts +++ b/lib/validation.ts @@ -71,8 +71,16 @@ export const sessionFilterSchema = z.object({ "UNRECOGNIZED_OTHER", ]) .optional(), + language: z + .string() + .regex(/^[a-z]{2}$/) + .optional(), startDate: z.string().datetime().optional(), endDate: z.string().datetime().optional(), + sortKey: z + .enum(["startTime", "category", "language", "sentiment", "sessionId"]) + .default("startTime"), + sortOrder: z.enum(["asc", "desc"]).default("desc"), page: z.number().int().min(1).default(1), limit: z.number().int().min(1).max(100).default(20), }); diff --git a/server/routers/dashboard.ts b/server/routers/dashboard.ts index df9186a..9be731b 100644 --- a/server/routers/dashboard.ts +++ b/server/routers/dashboard.ts @@ -21,8 +21,18 @@ export const dashboardRouter = router({ getSessions: companyProcedure .input(sessionFilterSchema) .query(async ({ input, ctx }) => { - const { search, sentiment, category, startDate, endDate, page, limit } = - input; + const { + search, + sentiment, + category, + language, + startDate, + endDate, + sortKey, + sortOrder, + page, + limit, + } = input; // Build where clause const where: Prisma.SessionWhereInput = { @@ -44,6 +54,10 @@ export const dashboardRouter = router({ where.category = category; } + if (language) { + where.language = language; + } + if (startDate || endDate) { where.startTime = {}; if (startDate) { @@ -89,7 +103,7 @@ export const dashboardRouter = router({ orderBy: { order: "asc" }, }, }, - orderBy: { startTime: "desc" }, + orderBy: { [sortKey]: sortOrder }, skip: (page - 1) * limit, take: limit, }); diff --git a/tests/unit/validation.test.ts b/tests/unit/validation.test.ts index 178cf04..c4369ca 100644 --- a/tests/unit/validation.test.ts +++ b/tests/unit/validation.test.ts @@ -176,6 +176,36 @@ describe("Validation Schemas", () => { const data = { limit: 101 }; expect(sessionFilterSchema.safeParse(data).success).toBe(false); }); + + it("should validate valid language code", () => { + const data = { language: "en" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(true); + }); + + it("should invalidate invalid language code", () => { + const data = { language: "invalid" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(false); + }); + + it("should validate valid sortKey", () => { + const data = { sortKey: "startTime" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(true); + }); + + it("should invalidate invalid sortKey", () => { + const data = { sortKey: "invalid" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(false); + }); + + it("should validate valid sortOrder", () => { + const data = { sortOrder: "asc" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(true); + }); + + it("should invalidate invalid sortOrder", () => { + const data = { sortOrder: "invalid" }; + expect(sessionFilterSchema.safeParse(data).success).toBe(false); + }); }); describe("companySettingsSchema", () => {