feat: timeline UI overhaul with project/resource panel redesign, quick filters, and API improvements
Redesigned timeline project and resource panels with expanded detail views, added quick filter toolbar, improved drag handling, and enhanced vacation/entitlement router logic. Includes e2e test updates and minor API fixes. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -161,6 +161,21 @@ export const vacationRouter = createTRPCRouter({
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
// Ownership check: USER role can only create vacations for their own resource
|
||||
const isManager = userRecord.systemRole === "ADMIN" || userRecord.systemRole === "MANAGER";
|
||||
if (!isManager) {
|
||||
const resource = await ctx.db.resource.findUnique({
|
||||
where: { id: input.resourceId },
|
||||
select: { userId: true },
|
||||
});
|
||||
if (!resource || resource.userId !== userRecord.id) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "You can only create vacation requests for your own resource",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlapping APPROVED or PENDING vacations
|
||||
const overlapping = await ctx.db.vacation.findFirst({
|
||||
where: {
|
||||
@@ -177,7 +192,6 @@ export const vacationRouter = createTRPCRouter({
|
||||
});
|
||||
}
|
||||
|
||||
const isManager = userRecord.systemRole === "ADMIN" || userRecord.systemRole === "MANAGER";
|
||||
const status = isManager ? VacationStatus.APPROVED : VacationStatus.PENDING;
|
||||
|
||||
const vacation = await ctx.db.vacation.create({
|
||||
@@ -354,6 +368,30 @@ export const vacationRouter = createTRPCRouter({
|
||||
throw new TRPCError({ code: "BAD_REQUEST", message: "Already cancelled" });
|
||||
}
|
||||
|
||||
// Ownership check: USER can only cancel their own vacations
|
||||
const userRecord = await ctx.db.user.findUnique({
|
||||
where: { email: ctx.session.user?.email ?? "" },
|
||||
select: { id: true, systemRole: true },
|
||||
});
|
||||
if (!userRecord) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
const isManagerOrAdmin = userRecord.systemRole === "ADMIN" || userRecord.systemRole === "MANAGER";
|
||||
if (!isManagerOrAdmin) {
|
||||
if (existing.requestedById !== userRecord.id) {
|
||||
const resource = await ctx.db.resource.findUnique({
|
||||
where: { id: existing.resourceId },
|
||||
select: { userId: true },
|
||||
});
|
||||
if (!resource || resource.userId !== userRecord.id) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "You can only cancel your own vacation requests",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updated = await ctx.db.vacation.update({
|
||||
where: { id: input.id },
|
||||
data: { status: VacationStatus.CANCELLED },
|
||||
|
||||
Reference in New Issue
Block a user