From 8b007f88d157d215e26adc59a5246f3e228f2621 Mon Sep 17 00:00:00 2001 From: Madalynn Nenninger Date: Thu, 12 Feb 2026 17:38:56 -0500 Subject: [PATCH 1/5] #3950 getAllProjects --- src/backend/src/controllers/projects.controllers.ts | 3 ++- src/backend/src/services/projects.services.ts | 4 ++-- src/frontend/src/apis/projects.api.ts | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/backend/src/controllers/projects.controllers.ts b/src/backend/src/controllers/projects.controllers.ts index 438b02005b..d060d2c862 100644 --- a/src/backend/src/controllers/projects.controllers.ts +++ b/src/backend/src/controllers/projects.controllers.ts @@ -25,7 +25,8 @@ export default class ProjectsController { static async getAllProjects(req: Request, res: Response, next: NextFunction) { try { - const projects: ProjectPreview[] = await ProjectsService.getAllProjects(req.organization); + const { carId } = req.query; + const projects: ProjectPreview[] = await ProjectsService.getAllProjects(req.organization, carId as string | undefined); res.status(200).json(projects); } catch (error: unknown) { next(error); diff --git a/src/backend/src/services/projects.services.ts b/src/backend/src/services/projects.services.ts index 44cda2e7cc..109ceab2e4 100644 --- a/src/backend/src/services/projects.services.ts +++ b/src/backend/src/services/projects.services.ts @@ -63,9 +63,9 @@ export default class ProjectsService { * @param organization the organization the user is in * @returns all the projects with preview query args */ - static async getAllProjects(organization: Organization): Promise { + static async getAllProjects(organization: Organization, carId?: string): Promise { const projects = await prisma.project.findMany({ - where: { wbsElement: { dateDeleted: null, organizationId: organization.organizationId } }, + where: { wbsElement: { dateDeleted: null, organizationId: organization.organizationId }, ...(carId && { carId }) }, ...getProjectPreviewQueryArgs(organization.organizationId) }); diff --git a/src/frontend/src/apis/projects.api.ts b/src/frontend/src/apis/projects.api.ts index e5d3ce62a4..5de3623ac2 100644 --- a/src/frontend/src/apis/projects.api.ts +++ b/src/frontend/src/apis/projects.api.ts @@ -40,6 +40,7 @@ export const getAllProjectsGantt = () => { */ export const getAllProjects = () => { return axios.get(apiUrls.allProjectPreviews(), { + params: { carId } transformResponse: (data) => JSON.parse(data).map(projectPreviewTransformer) }); }; From 4c24a7ac6577a23fe3eb325d2246d965548e7334 Mon Sep 17 00:00:00 2001 From: Madalynn Nenninger Date: Thu, 12 Feb 2026 17:44:39 -0500 Subject: [PATCH 2/5] #3950 fixed api function --- src/frontend/src/apis/projects.api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/apis/projects.api.ts b/src/frontend/src/apis/projects.api.ts index 5de3623ac2..27a737a5c0 100644 --- a/src/frontend/src/apis/projects.api.ts +++ b/src/frontend/src/apis/projects.api.ts @@ -38,9 +38,9 @@ export const getAllProjectsGantt = () => { /** * Fetches all projects with preview querry args */ -export const getAllProjects = () => { +export const getAllProjects = (carId?: string) => { return axios.get(apiUrls.allProjectPreviews(), { - params: { carId } + params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectPreviewTransformer) }); }; From 05959a9abc8334d1f01b75d29f6cf9ebf023b7b2 Mon Sep 17 00:00:00 2001 From: Madalynn Nenninger Date: Mon, 16 Feb 2026 15:34:51 -0500 Subject: [PATCH 3/5] #3950 modified endpoints to include optional car id --- .../src/controllers/projects.controllers.ts | 27 ++++++++++++++++--- src/backend/src/services/projects.services.ts | 19 +++++++------ src/frontend/src/apis/projects.api.ts | 9 ++++--- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/backend/src/controllers/projects.controllers.ts b/src/backend/src/controllers/projects.controllers.ts index d060d2c862..c3a587cf84 100644 --- a/src/backend/src/controllers/projects.controllers.ts +++ b/src/backend/src/controllers/projects.controllers.ts @@ -16,7 +16,11 @@ import BillOfMaterialsService from '../services/boms.services.js'; export default class ProjectsController { static async getAllProjectsGantt(req: Request, res: Response, next: NextFunction) { try { - const projects: ProjectGantt[] = await ProjectsService.getAllProjectsGantt(req.organization); + const { carId } = req.query; + const projects: ProjectGantt[] = await ProjectsService.getAllProjectsGantt( + req.organization, + carId as string | undefined + ); res.status(200).json(projects); } catch (error: unknown) { next(error); @@ -35,7 +39,12 @@ export default class ProjectsController { static async getUsersTeamsProjects(req: Request, res: Response, next: NextFunction) { try { - const projects: ProjectOverview[] = await ProjectsService.getUsersTeamsProjects(req.currentUser, req.organization); + const { carId } = req.query; + const projects: ProjectOverview[] = await ProjectsService.getUsersTeamsProjects( + req.currentUser, + req.organization, + carId as string | undefined + ); res.status(200).json(projects); } catch (error: unknown) { next(error); @@ -44,7 +53,12 @@ export default class ProjectsController { static async getUsersLeadingProjects(req: Request, res: Response, next: NextFunction) { try { - const projects: ProjectOverview[] = await ProjectsService.getUsersLeadingProjects(req.currentUser, req.organization); + const { carId } = req.query; + const projects: ProjectOverview[] = await ProjectsService.getUsersLeadingProjects( + req.currentUser, + req.organization, + carId as string | undefined + ); res.status(200).json(projects); } catch (error: unknown) { next(error); @@ -54,7 +68,12 @@ export default class ProjectsController { static async getTeamsProjects(req: Request, res: Response, next: NextFunction) { try { const { teamId } = req.params as Record; - const projects: Project[] = await ProjectsService.getTeamsProjects(req.organization, teamId); + const { carId } = req.query; + const projects: Project[] = await ProjectsService.getTeamsProjects( + req.organization, + teamId, + carId as string | undefined + ); res.status(200).json(projects); } catch (error: unknown) { next(error); diff --git a/src/backend/src/services/projects.services.ts b/src/backend/src/services/projects.services.ts index 109ceab2e4..11c60bdfce 100644 --- a/src/backend/src/services/projects.services.ts +++ b/src/backend/src/services/projects.services.ts @@ -49,9 +49,9 @@ export default class ProjectsService { * @param organization the organization the user is currently in * @returns all the projects with query args for use in the gantt chart */ - static async getAllProjectsGantt(organization: Organization): Promise { + static async getAllProjectsGantt(organization: Organization, carId?: string): Promise { const projects = await prisma.project.findMany({ - where: { wbsElement: { dateDeleted: null, organizationId: organization.organizationId } }, + where: { wbsElement: { dateDeleted: null, organizationId: organization.organizationId }, ...(carId && { carId }) }, ...getProjectGanttQueryArgs(organization.organizationId) }); @@ -78,14 +78,15 @@ export default class ProjectsService { * @param organization the oranization the user is in * @returns the projects the user is a lead or manager of with preview query args */ - static async getUsersLeadingProjects(user: User, organization: Organization): Promise { + static async getUsersLeadingProjects(user: User, organization: Organization, carId?: string): Promise { const projects = await prisma.project.findMany({ where: { wbsElement: { organizationId: organization.organizationId, dateDeleted: null, OR: [{ leadId: user.userId }, { managerId: user.userId }] - } + }, + ...(carId && { carId }) }, ...getProjectOverviewQueryArgs(organization.organizationId) }); @@ -99,7 +100,7 @@ export default class ProjectsService { * @param organization the organization the user is in * @returns all projects associated with teams the user is on with overview card query args */ - static async getUsersTeamsProjects(user: User, organization: Organization): Promise { + static async getUsersTeamsProjects(user: User, organization: Organization, carId?: string): Promise { const projects = await prisma.project.findMany({ where: { wbsElement: { @@ -128,7 +129,8 @@ export default class ProjectsService { } ] } - } + }, + ...(carId && { carId }) }, ...getProjectOverviewQueryArgs(organization.organizationId) }); @@ -142,7 +144,7 @@ export default class ProjectsService { * @param teamId * @returns all the projects for the given team with full project query args */ - static async getTeamsProjects(organization: Organization, teamId: string): Promise { + static async getTeamsProjects(organization: Organization, teamId: string, carId?: string): Promise { const projects = await prisma.project.findMany({ where: { wbsElement: { @@ -153,7 +155,8 @@ export default class ProjectsService { some: { teamId } - } + }, + ...(carId && { carId }) }, ...getProjectQueryArgs(organization.organizationId) }); diff --git a/src/frontend/src/apis/projects.api.ts b/src/frontend/src/apis/projects.api.ts index 27a737a5c0..b9b2650ee3 100644 --- a/src/frontend/src/apis/projects.api.ts +++ b/src/frontend/src/apis/projects.api.ts @@ -29,8 +29,9 @@ import { CreateSingleProjectPayload, EditSingleProjectPayload } from '../utils/t /** * Fetches all projects with querry args needed for Gantt chart */ -export const getAllProjectsGantt = () => { +export const getAllProjectsGantt = (carId?: string) => { return axios.get(apiUrls.allProjectsGantt(), { + params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectGanttTransformer) }); }; @@ -48,8 +49,9 @@ export const getAllProjects = (carId?: string) => { /** * Fetches all the projects that are on the users teams */ -export const getUsersTeamsProjects = () => { +export const getUsersTeamsProjects = (carId?: string) => { return axios.get(apiUrls.usersTeamsProjects(), { + params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectOverviewTransformer) }); }; @@ -57,8 +59,9 @@ export const getUsersTeamsProjects = () => { /** * Fetches all projects that the user is the manager or lead of. */ -export const getUsersLeadingProjects = () => { +export const getUsersLeadingProjects = (carId?: string) => { return axios.get(apiUrls.usersLeadingProjects(), { + params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectOverviewTransformer) }); }; From 14d52b601b2d61e602130e7606b20e7d5848fb6e Mon Sep 17 00:00:00 2001 From: Madalynn Nenninger Date: Mon, 16 Feb 2026 16:37:34 -0500 Subject: [PATCH 4/5] #3950 docs for car filtering --- src/backend/src/services/projects.services.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/src/services/projects.services.ts b/src/backend/src/services/projects.services.ts index 11c60bdfce..b6cfd74db9 100644 --- a/src/backend/src/services/projects.services.ts +++ b/src/backend/src/services/projects.services.ts @@ -47,6 +47,7 @@ export default class ProjectsService { /** * Get all the non deleted projects in the database for the given organization * @param organization the organization the user is currently in + * @param carId optional car id to filter projects by * @returns all the projects with query args for use in the gantt chart */ static async getAllProjectsGantt(organization: Organization, carId?: string): Promise { @@ -61,6 +62,7 @@ export default class ProjectsService { /** * Get all projects for given organization * @param organization the organization the user is in + * @param carId optional car id to filter projects by * @returns all the projects with preview query args */ static async getAllProjects(organization: Organization, carId?: string): Promise { @@ -76,6 +78,7 @@ export default class ProjectsService { * Get all projects that the user is the lead or manager of * @param user the user making the request * @param organization the oranization the user is in + * @param carId optional car id to filter projects by * @returns the projects the user is a lead or manager of with preview query args */ static async getUsersLeadingProjects(user: User, organization: Organization, carId?: string): Promise { @@ -98,6 +101,7 @@ export default class ProjectsService { * Get all projects related to teams the user is on * @param user the user making the request * @param organization the organization the user is in + * @param carId optional car id to filter projects by * @returns all projects associated with teams the user is on with overview card query args */ static async getUsersTeamsProjects(user: User, organization: Organization, carId?: string): Promise { @@ -142,6 +146,7 @@ export default class ProjectsService { * Get the projects for a given team * @param organization * @param teamId + * @param carId optional car id to filter projects by * @returns all the projects for the given team with full project query args */ static async getTeamsProjects(organization: Organization, teamId: string, carId?: string): Promise { From 5d21f7cc8e9493a1ec5fe2d1a3c871ec1cdd935e Mon Sep 17 00:00:00 2001 From: Madalynn Nenninger Date: Tue, 24 Feb 2026 19:34:56 -0500 Subject: [PATCH 5/5] #3950 udpated endpoint to use middleware to get car info --- src/backend/custom.d.ts | 3 ++- .../src/controllers/projects.controllers.ts | 22 +++++-------------- src/frontend/src/apis/projects.api.ts | 12 ++++------ 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/backend/custom.d.ts b/src/backend/custom.d.ts index 964ba270d6..99f4413227 100644 --- a/src/backend/custom.d.ts +++ b/src/backend/custom.d.ts @@ -1,4 +1,4 @@ -import { Organization } from '@prisma/client'; +import { Car, Organization } from '@prisma/client'; import { User as SharedUser } from 'shared'; declare global { @@ -6,6 +6,7 @@ declare global { export interface Request { currentUser: SharedUser; organization: Organization; + currentCar?: Car; } } } diff --git a/src/backend/src/controllers/projects.controllers.ts b/src/backend/src/controllers/projects.controllers.ts index c3a587cf84..4dd0938397 100644 --- a/src/backend/src/controllers/projects.controllers.ts +++ b/src/backend/src/controllers/projects.controllers.ts @@ -16,11 +16,7 @@ import BillOfMaterialsService from '../services/boms.services.js'; export default class ProjectsController { static async getAllProjectsGantt(req: Request, res: Response, next: NextFunction) { try { - const { carId } = req.query; - const projects: ProjectGantt[] = await ProjectsService.getAllProjectsGantt( - req.organization, - carId as string | undefined - ); + const projects: ProjectGantt[] = await ProjectsService.getAllProjectsGantt(req.organization, req.currentCar?.carId); res.status(200).json(projects); } catch (error: unknown) { next(error); @@ -29,8 +25,7 @@ export default class ProjectsController { static async getAllProjects(req: Request, res: Response, next: NextFunction) { try { - const { carId } = req.query; - const projects: ProjectPreview[] = await ProjectsService.getAllProjects(req.organization, carId as string | undefined); + const projects: ProjectPreview[] = await ProjectsService.getAllProjects(req.organization, req.currentCar?.carId); res.status(200).json(projects); } catch (error: unknown) { next(error); @@ -39,11 +34,10 @@ export default class ProjectsController { static async getUsersTeamsProjects(req: Request, res: Response, next: NextFunction) { try { - const { carId } = req.query; const projects: ProjectOverview[] = await ProjectsService.getUsersTeamsProjects( req.currentUser, req.organization, - carId as string | undefined + req.currentCar?.carId ); res.status(200).json(projects); } catch (error: unknown) { @@ -53,11 +47,10 @@ export default class ProjectsController { static async getUsersLeadingProjects(req: Request, res: Response, next: NextFunction) { try { - const { carId } = req.query; const projects: ProjectOverview[] = await ProjectsService.getUsersLeadingProjects( req.currentUser, req.organization, - carId as string | undefined + req.currentCar?.carId ); res.status(200).json(projects); } catch (error: unknown) { @@ -68,12 +61,7 @@ export default class ProjectsController { static async getTeamsProjects(req: Request, res: Response, next: NextFunction) { try { const { teamId } = req.params as Record; - const { carId } = req.query; - const projects: Project[] = await ProjectsService.getTeamsProjects( - req.organization, - teamId, - carId as string | undefined - ); + const projects: Project[] = await ProjectsService.getTeamsProjects(req.organization, teamId, req.currentCar?.carId); res.status(200).json(projects); } catch (error: unknown) { next(error); diff --git a/src/frontend/src/apis/projects.api.ts b/src/frontend/src/apis/projects.api.ts index b9b2650ee3..e5d3ce62a4 100644 --- a/src/frontend/src/apis/projects.api.ts +++ b/src/frontend/src/apis/projects.api.ts @@ -29,9 +29,8 @@ import { CreateSingleProjectPayload, EditSingleProjectPayload } from '../utils/t /** * Fetches all projects with querry args needed for Gantt chart */ -export const getAllProjectsGantt = (carId?: string) => { +export const getAllProjectsGantt = () => { return axios.get(apiUrls.allProjectsGantt(), { - params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectGanttTransformer) }); }; @@ -39,9 +38,8 @@ export const getAllProjectsGantt = (carId?: string) => { /** * Fetches all projects with preview querry args */ -export const getAllProjects = (carId?: string) => { +export const getAllProjects = () => { return axios.get(apiUrls.allProjectPreviews(), { - params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectPreviewTransformer) }); }; @@ -49,9 +47,8 @@ export const getAllProjects = (carId?: string) => { /** * Fetches all the projects that are on the users teams */ -export const getUsersTeamsProjects = (carId?: string) => { +export const getUsersTeamsProjects = () => { return axios.get(apiUrls.usersTeamsProjects(), { - params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectOverviewTransformer) }); }; @@ -59,9 +56,8 @@ export const getUsersTeamsProjects = (carId?: string) => { /** * Fetches all projects that the user is the manager or lead of. */ -export const getUsersLeadingProjects = (carId?: string) => { +export const getUsersLeadingProjects = () => { return axios.get(apiUrls.usersLeadingProjects(), { - params: { carId }, transformResponse: (data) => JSON.parse(data).map(projectOverviewTransformer) }); };