79 lines
2.1 KiB
TypeScript
79 lines
2.1 KiB
TypeScript
import type { APIRoute } from 'astro';
|
|
import { db } from '../../../db';
|
|
import { timeEntries, members, timeEntryTags, categories } from '../../../db/schema';
|
|
import { eq, and, isNull } from 'drizzle-orm';
|
|
import { nanoid } from 'nanoid';
|
|
|
|
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 categoryId = body.categoryId;
|
|
const tags = body.tags || [];
|
|
|
|
if (!clientId) {
|
|
return new Response('Client is required', { status: 400 });
|
|
}
|
|
|
|
if (!categoryId) {
|
|
return new Response('Category is required', { status: 400 });
|
|
}
|
|
|
|
// Check for running entry
|
|
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 });
|
|
}
|
|
|
|
// Get default org (first one)
|
|
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 });
|
|
}
|
|
|
|
// Verify category belongs to user's organization
|
|
const category = await db.select().from(categories).where(
|
|
and(
|
|
eq(categories.id, categoryId),
|
|
eq(categories.organizationId, member.organizationId)
|
|
)
|
|
).get();
|
|
|
|
if (!category) {
|
|
return new Response('Invalid category', { status: 400 });
|
|
}
|
|
|
|
const startTime = new Date();
|
|
const id = nanoid();
|
|
|
|
await db.insert(timeEntries).values({
|
|
id,
|
|
userId: locals.user.id,
|
|
organizationId: member.organizationId,
|
|
clientId,
|
|
categoryId,
|
|
startTime,
|
|
description,
|
|
});
|
|
|
|
// Add tags if provided
|
|
if (tags.length > 0) {
|
|
await db.insert(timeEntryTags).values(
|
|
tags.map((tagId: string) => ({
|
|
timeEntryId: id,
|
|
tagId,
|
|
}))
|
|
);
|
|
}
|
|
|
|
return new Response(JSON.stringify({ id, startTime }), { status: 200 });
|
|
};
|