o134's picture
Upload folder using huggingface_hub
1804b24 verified
Raw
History Blame Contribute Delete
5.47 kB
import { Router } from "express";
import { db, projectsTable, clientsTable, timeEntriesTable } from "@workspace/db";
import { eq, sql, and } from "drizzle-orm";
import {
CreateProjectBody,
UpdateProjectBody,
ListProjectsQueryParams,
GetProjectParams,
UpdateProjectParams,
DeleteProjectParams,
} from "@workspace/api-zod";
const router = Router();
router.get("/projects", async (req, res) => {
const query = ListProjectsQueryParams.safeParse(req.query);
if (!query.success) {
res.status(400).json({ error: query.error.message });
return;
}
const { status, clientId } = query.data;
const rows = await db
.select({
id: projectsTable.id,
title: projectsTable.title,
description: projectsTable.description,
clientId: projectsTable.clientId,
clientName: clientsTable.name,
status: projectsTable.status,
priority: projectsTable.priority,
budget: projectsTable.budget,
deadline: projectsTable.deadline,
driveUrl: projectsTable.driveUrl,
planUrl: projectsTable.planUrl,
createdAt: projectsTable.createdAt,
updatedAt: projectsTable.updatedAt,
})
.from(projectsTable)
.leftJoin(clientsTable, eq(projectsTable.clientId, clientsTable.id))
.where(
and(
eq(projectsTable.userId, req.user!.id),
status && clientId
? sql`${projectsTable.status} = ${status} AND ${projectsTable.clientId} = ${clientId}`
: status
? eq(projectsTable.status, status)
: clientId
? eq(projectsTable.clientId, clientId)
: undefined
)
)
.orderBy(projectsTable.createdAt);
const withHours = await Promise.all(
rows.map(async (p) => {
const [{ total }] = await db
.select({ total: sql<number>`coalesce(sum(${timeEntriesTable.hours}), 0)` })
.from(timeEntriesTable)
.where(eq(timeEntriesTable.projectId, p.id));
return { ...p, totalHours: total };
})
);
res.json(withHours);
});
router.post("/projects", async (req, res) => {
const body = CreateProjectBody.safeParse(req.body);
if (!body.success) {
res.status(400).json({ error: body.error.message });
return;
}
const [project] = await db.insert(projectsTable).values({ ...body.data, userId: req.user!.id }).returning();
let clientName: string | null = null;
if (project.clientId) {
const [client] = await db.select().from(clientsTable).where(eq(clientsTable.id, project.clientId));
clientName = client?.name ?? null;
}
res.status(201).json({ ...project, clientName, totalHours: 0 });
});
router.get("/projects/:id", async (req, res) => {
const params = GetProjectParams.safeParse({ id: Number(req.params.id) });
if (!params.success) {
res.status(400).json({ error: params.error.message });
return;
}
const [project] = await db
.select({
id: projectsTable.id,
title: projectsTable.title,
description: projectsTable.description,
clientId: projectsTable.clientId,
clientName: clientsTable.name,
status: projectsTable.status,
priority: projectsTable.priority,
budget: projectsTable.budget,
deadline: projectsTable.deadline,
driveUrl: projectsTable.driveUrl,
planUrl: projectsTable.planUrl,
createdAt: projectsTable.createdAt,
updatedAt: projectsTable.updatedAt,
})
.from(projectsTable)
.leftJoin(clientsTable, eq(projectsTable.clientId, clientsTable.id))
.where(and(eq(projectsTable.id, params.data.id), eq(projectsTable.userId, req.user!.id)));
if (!project) {
res.status(404).json({ error: "Project not found" });
return;
}
const [{ total }] = await db
.select({ total: sql<number>`coalesce(sum(${timeEntriesTable.hours}), 0)` })
.from(timeEntriesTable)
.where(eq(timeEntriesTable.projectId, project.id));
res.json({ ...project, totalHours: total });
});
router.patch("/projects/:id", async (req, res) => {
const params = UpdateProjectParams.safeParse({ id: Number(req.params.id) });
if (!params.success) {
res.status(400).json({ error: params.error.message });
return;
}
const body = UpdateProjectBody.safeParse(req.body);
if (!body.success) {
res.status(400).json({ error: body.error.message });
return;
}
const [project] = await db
.update(projectsTable)
.set(body.data)
.where(and(eq(projectsTable.id, params.data.id), eq(projectsTable.userId, req.user!.id)))
.returning();
if (!project) {
res.status(404).json({ error: "Project not found" });
return;
}
let clientName: string | null = null;
if (project.clientId) {
const [client] = await db.select().from(clientsTable).where(eq(clientsTable.id, project.clientId));
clientName = client?.name ?? null;
}
const [{ total }] = await db
.select({ total: sql<number>`coalesce(sum(${timeEntriesTable.hours}), 0)` })
.from(timeEntriesTable)
.where(eq(timeEntriesTable.projectId, project.id));
res.json({ ...project, clientName, totalHours: total });
});
router.delete("/projects/:id", async (req, res) => {
const params = DeleteProjectParams.safeParse({ id: Number(req.params.id) });
if (!params.success) {
res.status(400).json({ error: params.error.message });
return;
}
await db.delete(projectsTable).where(and(eq(projectsTable.id, params.data.id), eq(projectsTable.userId, req.user!.id)));
res.status(204).send();
});
export default router;