feat: basic workspace search (#203)
* feat: set up command pallette and search endpoint * feat: use placeholder data in search results * feat: add keyboard navigation * feat: add icons for search results * feat: add fuzzy search * feat: add search button to collapsed menu * feat: add keyboard shortcuts * fix: prevent no results flickering * feat: consistent font size for search placeholder * chore: build translations
This commit is contained in:
@@ -409,4 +409,80 @@ export const workspaceRouter = createTRPCRouter({
|
||||
isReserved: workspaceSlug?.type === "reserved",
|
||||
};
|
||||
}),
|
||||
search: protectedProcedure
|
||||
.meta({
|
||||
openapi: {
|
||||
summary: "Search boards and cards in a workspace",
|
||||
method: "GET",
|
||||
path: "/workspaces/{workspacePublicId}/search",
|
||||
description:
|
||||
"Searches for boards and cards by title within a workspace",
|
||||
tags: ["Workspaces"],
|
||||
protect: true,
|
||||
},
|
||||
})
|
||||
.input(
|
||||
z.object({
|
||||
workspacePublicId: z.string().min(12),
|
||||
query: z.string().min(1).max(100),
|
||||
limit: z.number().min(1).max(50).optional().default(20),
|
||||
}),
|
||||
)
|
||||
.output(
|
||||
z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
publicId: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string().nullable(),
|
||||
slug: z.string(),
|
||||
updatedAt: z.date().nullable(),
|
||||
createdAt: z.date(),
|
||||
type: z.literal("board"),
|
||||
}),
|
||||
z.object({
|
||||
publicId: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string().nullable(),
|
||||
boardPublicId: z.string(),
|
||||
boardName: z.string(),
|
||||
listName: z.string(),
|
||||
updatedAt: z.date().nullable(),
|
||||
createdAt: z.date(),
|
||||
type: z.literal("card"),
|
||||
}),
|
||||
]),
|
||||
),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const userId = ctx.user?.id;
|
||||
|
||||
if (!userId)
|
||||
throw new TRPCError({
|
||||
message: `User not authenticated`,
|
||||
code: "UNAUTHORIZED",
|
||||
});
|
||||
|
||||
const workspace = await workspaceRepo.getByPublicId(
|
||||
ctx.db,
|
||||
input.workspacePublicId,
|
||||
);
|
||||
|
||||
if (!workspace)
|
||||
throw new TRPCError({
|
||||
message: `Workspace not found`,
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
|
||||
await assertUserInWorkspace(ctx.db, userId, workspace.id);
|
||||
|
||||
const result = await workspaceRepo.searchBoardsAndCards(
|
||||
ctx.db,
|
||||
workspace.id,
|
||||
input.query,
|
||||
input.limit,
|
||||
);
|
||||
|
||||
return result;
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user