refactor: consolidate duplicated code across web and API packages
- Extract shared render helpers (vacation blocks, range overlay, overbooking blink) into renderHelpers.tsx - Centralize status badge styles and vacation color maps into status-styles.ts - Extract dragMath.ts utility from useTimelineDrag for reuse - Split useInvalidatePlanningViews into useInvalidateTimeline (4 queries) + useInvalidatePlanningViews (8 queries) - Adopt findUniqueOrThrow() and Prisma select constants across API routers - Add shared fmtEur() helper for API-side money formatting - Wrap TimelineResourcePanel and TimelineProjectPanel with React.memo - Fix pre-existing TS2589 deep type errors in TeamCalendar and VacationModal - 38 files changed, reducing ~400 lines of duplicated code Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -295,30 +295,30 @@ export const resourceRouter = createTRPCRouter({
|
||||
getHoverCard: protectedProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const resource = await ctx.db.resource.findUnique({
|
||||
where: { id: input.id },
|
||||
select: {
|
||||
id: true,
|
||||
displayName: true,
|
||||
eid: true,
|
||||
email: true,
|
||||
chapter: true,
|
||||
lcrCents: true,
|
||||
ucrCents: true,
|
||||
currency: true,
|
||||
chargeabilityTarget: true,
|
||||
skills: true,
|
||||
availability: true,
|
||||
isActive: true,
|
||||
areaRole: { select: { id: true, name: true, color: true } },
|
||||
country: { select: { name: true, code: true } },
|
||||
managementLevel: { select: { name: true } },
|
||||
resourceType: true,
|
||||
},
|
||||
});
|
||||
if (!resource) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: "Resource not found" });
|
||||
}
|
||||
const resource = await findUniqueOrThrow(
|
||||
ctx.db.resource.findUnique({
|
||||
where: { id: input.id },
|
||||
select: {
|
||||
id: true,
|
||||
displayName: true,
|
||||
eid: true,
|
||||
email: true,
|
||||
chapter: true,
|
||||
lcrCents: true,
|
||||
ucrCents: true,
|
||||
currency: true,
|
||||
chargeabilityTarget: true,
|
||||
skills: true,
|
||||
availability: true,
|
||||
isActive: true,
|
||||
areaRole: { select: ROLE_BRIEF_SELECT },
|
||||
country: { select: { name: true, code: true } },
|
||||
managementLevel: { select: { name: true } },
|
||||
resourceType: true,
|
||||
},
|
||||
}),
|
||||
"Resource",
|
||||
);
|
||||
const directory = await getAnonymizationDirectory(ctx.db);
|
||||
const anon = anonymizeResource(resource, directory);
|
||||
return {
|
||||
@@ -633,11 +633,14 @@ export const resourceRouter = createTRPCRouter({
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
// Find the resource linked to this user
|
||||
const user = await ctx.db.user.findUnique({
|
||||
where: { email: ctx.session.user?.email ?? "" },
|
||||
include: { resource: true },
|
||||
});
|
||||
if (!user?.resource) {
|
||||
const user = await findUniqueOrThrow(
|
||||
ctx.db.user.findUnique({
|
||||
where: { email: ctx.session.user?.email ?? "" },
|
||||
include: { resource: true },
|
||||
}),
|
||||
"User",
|
||||
);
|
||||
if (!user.resource) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: "No resource linked to your account" });
|
||||
}
|
||||
const resourceId = user.resource.id;
|
||||
@@ -748,17 +751,16 @@ export const resourceRouter = createTRPCRouter({
|
||||
.input(z.object({ resourceId: z.string() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const [resource, settings] = await Promise.all([
|
||||
ctx.db.resource.findUnique({
|
||||
where: { id: input.resourceId },
|
||||
include: { areaRole: { select: { name: true } } },
|
||||
}),
|
||||
findUniqueOrThrow(
|
||||
ctx.db.resource.findUnique({
|
||||
where: { id: input.resourceId },
|
||||
include: { areaRole: { select: { name: true } } },
|
||||
}),
|
||||
"Resource",
|
||||
),
|
||||
ctx.db.systemSettings.findUnique({ where: { id: "singleton" } }),
|
||||
]);
|
||||
|
||||
if (!resource) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: "Resource not found" });
|
||||
}
|
||||
|
||||
if (!isAiConfigured(settings)) {
|
||||
throw new TRPCError({
|
||||
code: "PRECONDITION_FAILED",
|
||||
|
||||
Reference in New Issue
Block a user