feat: US-006 — Project tRPC procedures (CRUD)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { initTRPC } from '@trpc/server';
|
import { initTRPC } from '@trpc/server';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { eq, asc, inArray } from 'drizzle-orm';
|
import { eq, asc, inArray, and } from 'drizzle-orm';
|
||||||
import { getDb } from '../db';
|
import { getDb } from '../db';
|
||||||
import { clients, projects, tasks } from '../db/schema';
|
import { clients, projects, tasks } from '../db/schema';
|
||||||
import { getStore } from '../store';
|
import { getStore } from '../store';
|
||||||
@@ -101,14 +101,40 @@ const clientsRouter = router({
|
|||||||
const projectsRouter = router({
|
const projectsRouter = router({
|
||||||
list: publicProcedure
|
list: publicProcedure
|
||||||
.input(z.object({ clientId: z.string().optional(), includeArchived: z.boolean().optional() }).optional())
|
.input(z.object({ clientId: z.string().optional(), includeArchived: z.boolean().optional() }).optional())
|
||||||
.query(() => []),
|
.query(({ input }) => {
|
||||||
listAll: publicProcedure.query(() => [] as Array<{ id: string; name: string }>),
|
const where = and(
|
||||||
|
input?.clientId !== undefined ? eq(projects.clientId, input.clientId) : undefined,
|
||||||
|
!input?.includeArchived ? eq(projects.status, 'active') : undefined,
|
||||||
|
);
|
||||||
|
return getDb().select().from(projects).where(where).orderBy(asc(projects.name)).all();
|
||||||
|
}),
|
||||||
|
|
||||||
|
listAll: publicProcedure.query(() => {
|
||||||
|
return getDb().select({ id: projects.id, name: projects.name }).from(projects).orderBy(asc(projects.name)).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(projects).where(eq(projects.id, input.id)).all();
|
||||||
|
return result[0] ?? null;
|
||||||
|
}),
|
||||||
|
|
||||||
create: publicProcedure
|
create: publicProcedure
|
||||||
.input(z.object({ name: z.string(), clientId: z.string().optional() }))
|
.input(z.object({ name: z.string(), clientId: z.string().optional() }))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const now = Date.now();
|
||||||
|
getDb().insert(projects).values({
|
||||||
|
id,
|
||||||
|
name: input.name,
|
||||||
|
clientId: input.clientId ?? null,
|
||||||
|
status: 'active',
|
||||||
|
createdAt: now,
|
||||||
|
}).run();
|
||||||
|
return { id };
|
||||||
|
}),
|
||||||
|
|
||||||
update: publicProcedure
|
update: publicProcedure
|
||||||
.input(z.object({
|
.input(z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
@@ -117,10 +143,28 @@ const projectsRouter = router({
|
|||||||
status: z.enum(['active', 'archived']).optional(),
|
status: z.enum(['active', 'archived']).optional(),
|
||||||
aiSummary: z.string().optional(),
|
aiSummary: z.string().optional(),
|
||||||
}))
|
}))
|
||||||
.mutation(() => null),
|
.mutation(({ input }) => {
|
||||||
|
const set: Partial<{ name: string; clientId: string | null; status: 'active' | 'archived'; aiSummary: string | null }> = {};
|
||||||
|
if (input.name !== undefined) set.name = input.name;
|
||||||
|
if (input.clientId !== undefined) set.clientId = input.clientId;
|
||||||
|
if (input.status !== undefined) set.status = input.status;
|
||||||
|
if (input.aiSummary !== undefined) set.aiSummary = input.aiSummary;
|
||||||
|
if (Object.keys(set).length > 0) {
|
||||||
|
getDb().update(projects).set(set).where(eq(projects.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 }) => {
|
||||||
|
const db = getDb();
|
||||||
|
// Null out projectId on tasks belonging to this project
|
||||||
|
db.update(tasks).set({ projectId: null }).where(eq(tasks.projectId, input.id)).run();
|
||||||
|
// Delete the project
|
||||||
|
db.delete(projects).where(eq(projects.id, input.id)).run();
|
||||||
|
return { success: true as const };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const tasksRouter = router({
|
const tasksRouter = router({
|
||||||
|
|||||||
Reference in New Issue
Block a user