feat: US-008 — Checkpoint and Note tRPC procedures (CRUD)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|||||||
import { eq, asc, inArray, and, or, like, sql } from 'drizzle-orm';
|
import { eq, asc, inArray, and, or, like, sql } from 'drizzle-orm';
|
||||||
import { alias } from 'drizzle-orm/sqlite-core';
|
import { alias } from 'drizzle-orm/sqlite-core';
|
||||||
import { getDb } from '../db';
|
import { getDb } from '../db';
|
||||||
import { clients, projects, tasks } from '../db/schema';
|
import { clients, projects, tasks, checkpoints, notes } from '../db/schema';
|
||||||
import { getStore } from '../store';
|
import { getStore } from '../store';
|
||||||
|
|
||||||
const t = initTRPC.create();
|
const t = initTRPC.create();
|
||||||
@@ -295,7 +295,11 @@ const tasksRouter = router({
|
|||||||
const checkpointsRouter = router({
|
const checkpointsRouter = router({
|
||||||
list: publicProcedure
|
list: publicProcedure
|
||||||
.input(z.object({ projectId: z.string().optional() }).optional())
|
.input(z.object({ projectId: z.string().optional() }).optional())
|
||||||
.query(() => []),
|
.query(({ input }) => {
|
||||||
|
const where = input?.projectId !== undefined ? eq(checkpoints.projectId, input.projectId) : undefined;
|
||||||
|
return getDb().select().from(checkpoints).where(where).orderBy(asc(checkpoints.date)).all();
|
||||||
|
}),
|
||||||
|
|
||||||
create: publicProcedure
|
create: publicProcedure
|
||||||
.input(z.object({
|
.input(z.object({
|
||||||
projectId: z.string(),
|
projectId: z.string(),
|
||||||
@@ -304,7 +308,21 @@ const checkpointsRouter = router({
|
|||||||
isAiSuggested: z.number().optional(),
|
isAiSuggested: z.number().optional(),
|
||||||
isApproved: z.number().optional(),
|
isApproved: z.number().optional(),
|
||||||
}))
|
}))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const now = Date.now();
|
||||||
|
getDb().insert(checkpoints).values({
|
||||||
|
id,
|
||||||
|
projectId: input.projectId,
|
||||||
|
title: input.title,
|
||||||
|
date: input.date,
|
||||||
|
isAiSuggested: input.isAiSuggested ?? 0,
|
||||||
|
isApproved: input.isApproved ?? 0,
|
||||||
|
createdAt: now,
|
||||||
|
}).run();
|
||||||
|
return { id };
|
||||||
|
}),
|
||||||
|
|
||||||
update: publicProcedure
|
update: publicProcedure
|
||||||
.input(z.object({
|
.input(z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
@@ -312,28 +330,79 @@ const checkpointsRouter = router({
|
|||||||
date: z.number().optional(),
|
date: z.number().optional(),
|
||||||
isApproved: z.number().optional(),
|
isApproved: z.number().optional(),
|
||||||
}))
|
}))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const set: Partial<{ title: string; date: number; isApproved: number }> = {};
|
||||||
|
if (input.title !== undefined) set.title = input.title;
|
||||||
|
if (input.date !== undefined) set.date = input.date;
|
||||||
|
if (input.isApproved !== undefined) set.isApproved = input.isApproved;
|
||||||
|
if (Object.keys(set).length > 0) {
|
||||||
|
getDb().update(checkpoints).set(set).where(eq(checkpoints.id, input.id)).run();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}),
|
||||||
|
|
||||||
delete: publicProcedure
|
delete: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
getDb().delete(checkpoints).where(eq(checkpoints.id, input.id)).run();
|
||||||
|
return { success: true as const };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const notesRouter = router({
|
const notesRouter = router({
|
||||||
list: publicProcedure
|
list: publicProcedure
|
||||||
.input(z.object({ projectId: z.string().optional() }).optional())
|
.input(z.object({ projectId: z.string().optional() }).optional())
|
||||||
.query(() => []),
|
.query(({ input }) => {
|
||||||
|
const where = input?.projectId !== undefined ? eq(notes.projectId, input.projectId) : undefined;
|
||||||
|
return getDb()
|
||||||
|
.select({ id: notes.id, projectId: notes.projectId, title: notes.title, createdAt: notes.createdAt, updatedAt: notes.updatedAt })
|
||||||
|
.from(notes)
|
||||||
|
.where(where)
|
||||||
|
.orderBy(asc(notes.createdAt))
|
||||||
|
.all();
|
||||||
|
}),
|
||||||
|
|
||||||
get: publicProcedure
|
get: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.query(() => null),
|
.query(({ input }) => {
|
||||||
|
const result = getDb().select().from(notes).where(eq(notes.id, input.id)).all();
|
||||||
|
return result[0] ?? null;
|
||||||
|
}),
|
||||||
|
|
||||||
create: publicProcedure
|
create: publicProcedure
|
||||||
.input(z.object({ title: z.string(), content: z.string(), projectId: z.string().optional() }))
|
.input(z.object({ title: z.string(), content: z.string(), projectId: z.string().optional() }))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const now = Date.now();
|
||||||
|
getDb().insert(notes).values({
|
||||||
|
id,
|
||||||
|
title: input.title,
|
||||||
|
content: input.content,
|
||||||
|
projectId: input.projectId ?? null,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
}).run();
|
||||||
|
return { id };
|
||||||
|
}),
|
||||||
|
|
||||||
update: publicProcedure
|
update: publicProcedure
|
||||||
.input(z.object({ id: z.string(), title: z.string().optional(), content: z.string().optional() }))
|
.input(z.object({ id: z.string(), title: z.string().optional(), content: z.string().optional() }))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const set: Partial<{ title: string; content: string; updatedAt: number }> = {};
|
||||||
|
if (input.title !== undefined) set.title = input.title;
|
||||||
|
if (input.content !== undefined) set.content = input.content;
|
||||||
|
// Always update updatedAt
|
||||||
|
set.updatedAt = Date.now();
|
||||||
|
getDb().update(notes).set(set).where(eq(notes.id, input.id)).run();
|
||||||
|
return null;
|
||||||
|
}),
|
||||||
|
|
||||||
delete: publicProcedure
|
delete: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
getDb().delete(notes).where(eq(notes.id, input.id)).run();
|
||||||
|
return { success: true as const };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const settingsRouter = router({
|
const settingsRouter = router({
|
||||||
|
|||||||
Reference in New Issue
Block a user