feat: add due date filters
This commit is contained in:
@@ -13,6 +13,12 @@ import { generateSlug, generateUID } from "@kan/shared/utils";
|
||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||
import { assertUserInWorkspace } from "../utils/auth";
|
||||
|
||||
const dueDateFilterSchema = z.object({
|
||||
startDate: z.string().datetime().optional(),
|
||||
endDate: z.string().datetime().optional(),
|
||||
hasNoDueDate: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const boardRouter = createTRPCRouter({
|
||||
all: protectedProcedure
|
||||
.meta({
|
||||
@@ -79,6 +85,7 @@ export const boardRouter = createTRPCRouter({
|
||||
members: z.array(z.string().min(12)).optional(),
|
||||
labels: z.array(z.string().min(12)).optional(),
|
||||
lists: z.array(z.string().min(12)).optional(),
|
||||
dueDate: z.array(dueDateFilterSchema).optional(),
|
||||
type: z.enum(["regular", "template"]).optional(),
|
||||
}),
|
||||
)
|
||||
@@ -112,6 +119,14 @@ export const boardRouter = createTRPCRouter({
|
||||
members: input.members ?? [],
|
||||
labels: input.labels ?? [],
|
||||
lists: input.lists ?? [],
|
||||
dueDate:
|
||||
input.dueDate?.map((filter) => ({
|
||||
startDate: filter.startDate
|
||||
? new Date(filter.startDate)
|
||||
: undefined,
|
||||
endDate: filter.endDate ? new Date(filter.endDate) : undefined,
|
||||
hasNoDueDate: filter.hasNoDueDate,
|
||||
})) ?? [],
|
||||
type: input.type,
|
||||
},
|
||||
);
|
||||
@@ -145,6 +160,7 @@ export const boardRouter = createTRPCRouter({
|
||||
members: z.array(z.string().min(12)).optional(),
|
||||
labels: z.array(z.string().min(12)).optional(),
|
||||
lists: z.array(z.string().min(12)).optional(),
|
||||
dueDate: z.array(dueDateFilterSchema).optional(),
|
||||
}),
|
||||
)
|
||||
.output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>())
|
||||
@@ -168,6 +184,14 @@ export const boardRouter = createTRPCRouter({
|
||||
members: input.members ?? [],
|
||||
labels: input.labels ?? [],
|
||||
lists: input.lists ?? [],
|
||||
dueDate:
|
||||
input.dueDate?.map((filter) => ({
|
||||
startDate: filter.startDate
|
||||
? new Date(filter.startDate)
|
||||
: undefined,
|
||||
endDate: filter.endDate ? new Date(filter.endDate) : undefined,
|
||||
hasNoDueDate: filter.hasNoDueDate,
|
||||
})) ?? [],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -239,6 +263,7 @@ export const boardRouter = createTRPCRouter({
|
||||
members: [],
|
||||
labels: [],
|
||||
lists: [],
|
||||
dueDate: [],
|
||||
type: sourceBoardInfo.type,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
import { and, asc, desc, eq, inArray, isNull, or } from "drizzle-orm";
|
||||
import {
|
||||
and,
|
||||
asc,
|
||||
desc,
|
||||
eq,
|
||||
gte,
|
||||
inArray,
|
||||
isNotNull,
|
||||
isNull,
|
||||
lt,
|
||||
or,
|
||||
} from "drizzle-orm";
|
||||
|
||||
import type { dbClient } from "@kan/db/client";
|
||||
import type { BoardVisibilityStatus } from "@kan/db/schema";
|
||||
@@ -65,6 +76,39 @@ export const getIdByPublicId = async (db: dbClient, boardPublicId: string) => {
|
||||
return board;
|
||||
};
|
||||
|
||||
interface DueDateFilter {
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
hasNoDueDate?: boolean;
|
||||
}
|
||||
|
||||
const buildDueDateWhere = (filters: DueDateFilter[]) => {
|
||||
if (!filters.length) return undefined;
|
||||
|
||||
const clauses = filters
|
||||
.map((filter) => {
|
||||
const conditions: ReturnType<typeof and>[] = [];
|
||||
|
||||
if (filter.hasNoDueDate) {
|
||||
conditions.push(isNull(cards.dueDate));
|
||||
} else {
|
||||
conditions.push(isNotNull(cards.dueDate));
|
||||
|
||||
if (filter.startDate)
|
||||
conditions.push(gte(cards.dueDate, filter.startDate));
|
||||
|
||||
if (filter.endDate) conditions.push(lt(cards.dueDate, filter.endDate));
|
||||
}
|
||||
|
||||
return conditions.length > 0 ? and(...conditions) : undefined;
|
||||
})
|
||||
.filter((clause): clause is NonNullable<typeof clause> => !!clause);
|
||||
|
||||
if (!clauses.length) return undefined;
|
||||
|
||||
return or(...clauses);
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: dbClient,
|
||||
boardPublicId: string,
|
||||
@@ -72,6 +116,7 @@ export const getByPublicId = async (
|
||||
members: string[];
|
||||
labels: string[];
|
||||
lists: string[];
|
||||
dueDate: DueDateFilter[];
|
||||
type: "regular" | "template" | undefined;
|
||||
},
|
||||
) => {
|
||||
@@ -237,6 +282,7 @@ export const getByPublicId = async (
|
||||
where: and(
|
||||
cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined,
|
||||
isNull(cards.deletedAt),
|
||||
buildDueDateWhere(filters.dueDate),
|
||||
),
|
||||
orderBy: [asc(cards.index)],
|
||||
},
|
||||
@@ -292,6 +338,7 @@ export const getBySlug = async (
|
||||
members: string[];
|
||||
labels: string[];
|
||||
lists: string[];
|
||||
dueDate: DueDateFilter[];
|
||||
},
|
||||
) => {
|
||||
let cardIds: string[] = [];
|
||||
@@ -407,6 +454,7 @@ export const getBySlug = async (
|
||||
where: and(
|
||||
cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined,
|
||||
isNull(cards.deletedAt),
|
||||
buildDueDateWhere(filters.dueDate),
|
||||
),
|
||||
orderBy: [asc(cards.index)],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user