SPB Git
2.4 KB · 31 lines typescript
1/** Research tasks = rows of `tasks` scoped to a research page. */2import { and, asc, eq, isNull, sql as dsql } from "drizzle-orm";3import { db, schema } from "@/db";4import { HttpError } from "@/lib/auth/guard";5const T = schema.tasks;6export type TaskRow = typeof T.$inferSelect;7export interface TaskInput { pageId: string; title: string; status?: "todo" | "doing" | "done"; priority?: "low" | "medium" | "high"; dueAt?: string | null; project?: string | null }89export async function listTasks(wsId: string, pageId: string) {10  return db.select().from(T).where(and(eq(T.workspaceId, wsId), eq(T.pageId, pageId), isNull(T.deletedAt))).orderBy(dsql`(${T.status} = 'done') asc`, dsql`${T.dueAt} asc nulls last`, asc(T.createdAt));11}12export async function createTask(wsId: string, input: TaskInput) {13  const [t] = await db.insert(T).values({ workspaceId: wsId, pageId: input.pageId, title: input.title.trim() || "Task", status: input.status ?? "todo", priority: input.priority ?? "medium", dueAt: input.dueAt ? new Date(input.dueAt) : null, project: input.project ?? null, completedAt: input.status === "done" ? new Date() : null }).returning();14  return t;15}16export async function createTasks(wsId: string, pageId: string, items: Omit<TaskInput, "pageId">[]) {17  const out: TaskRow[] = []; for (const it of items) out.push(await createTask(wsId, { ...it, pageId })); return out;18}19export async function updateTask(wsId: string, id: string, patch: Partial<TaskInput>) {20  const [prev] = await db.select().from(T).where(and(eq(T.id, id), eq(T.workspaceId, wsId), isNull(T.deletedAt))); if (!prev) throw new HttpError(404, "Task not found");21  const set: Partial<TaskRow> = { updatedAt: new Date() };22  if (patch.title !== undefined) set.title = patch.title.trim() || prev.title;23  if (patch.status !== undefined) { set.status = patch.status; set.completedAt = patch.status === "done" ? (prev.completedAt ?? new Date()) : null; }24  if (patch.priority !== undefined) set.priority = patch.priority;25  if (patch.dueAt !== undefined) set.dueAt = patch.dueAt ? new Date(patch.dueAt) : null;26  if (patch.project !== undefined) set.project = patch.project;27  if (patch.pageId !== undefined) set.pageId = patch.pageId;28  const [t] = await db.update(T).set(set).where(eq(T.id, id)).returning(); return t;29}30export async function deleteTask(wsId: string, id: string) { await db.update(T).set({ deletedAt: new Date() }).where(and(eq(T.id, id), eq(T.workspaceId, wsId))); }31
Files · 2c37cb5a3e2af18e5ba361996d453cab97da82c2
Menu

Theme