Files
chronus/src/pages/api/time-entries/start.ts
Atridad Lahiji 815c08dd50
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m59s
Schema fixes
2026-01-20 12:08:06 -07:00

68 lines
1.7 KiB
TypeScript

import type { APIRoute } from "astro";
import { db } from "../../../db";
import { timeEntries, members } from "../../../db/schema";
import { eq, and, isNull } from "drizzle-orm";
import { nanoid } from "nanoid";
import { validateTimeEntryResources } from "../../../lib/validation";
export const POST: APIRoute = async ({ request, locals }) => {
if (!locals.user) return new Response("Unauthorized", { status: 401 });
const body = await request.json();
const description = body.description || "";
const clientId = body.clientId;
const tagId = body.tagId || null;
if (!clientId) {
return new Response("Client is required", { status: 400 });
}
const runningEntry = await db
.select()
.from(timeEntries)
.where(
and(eq(timeEntries.userId, locals.user.id), isNull(timeEntries.endTime)),
)
.get();
if (runningEntry) {
return new Response("Timer already running", { status: 400 });
}
const member = await db
.select()
.from(members)
.where(eq(members.userId, locals.user.id))
.limit(1)
.get();
if (!member) {
return new Response("No organization found", { status: 400 });
}
const validation = await validateTimeEntryResources({
organizationId: member.organizationId,
clientId,
tagId,
});
if (!validation.valid) {
return new Response(validation.error, { status: 400 });
}
const startTime = new Date();
const id = nanoid();
await db.insert(timeEntries).values({
id,
userId: locals.user.id,
organizationId: member.organizationId,
clientId,
tagId,
startTime,
description,
isManual: false,
});
return new Response(JSON.stringify({ id, startTime }), { status: 200 });
};