diff --git a/src/controllers/EventParticipantsController.js b/src/controllers/EventParticipantsController.js index 0f2829e..527c911 100644 --- a/src/controllers/EventParticipantsController.js +++ b/src/controllers/EventParticipantsController.js @@ -1,4 +1,5 @@ const EventParticipantsRepo = require('../repository/team/EventParticipantRepo'); +const TeamRepo = require('../repository/team/TeamRepo') const EventRepo = require('../repository/event/EventRepo') const UserRepo = require('../repository/user/UserRepo') @@ -10,15 +11,15 @@ class EventParticipantController{ const participants = await EventParticipantsRepo.findUnassignedParticipants(eventId); const nonBannedParticipants = participants.filter(p => - p.userDetails && p.userDetails.isBanned !== true && p.userDetails.isBanned !== 1 + p.participants && p.participants.isBanned !== true && p.participants.isBanned !== 1 ); const formattedParticipants = nonBannedParticipants.map(p => ({ id: p.userId, - firstName: p.userDetails?.firstName, - lastName: p.userDetails?.lastName, - email: p.userDetails?.email, - checkIn: p.userDetails?.checkIn, + firstName: p.participants?.firstName, + lastName: p.participants?.lastName, + email: p.participants?.email, + checkIn: p.participants?.checkIn, teamId: p.teamId })); @@ -96,6 +97,35 @@ class EventParticipantController{ return res.status(500).json({ message: 'Server error retrieving team status' }); } } + async getTeamsByEvent(eventId) { + return await Team.findAll({ + where: { + eventId: eventId + }, + include: [ + { + model: EventParticipant, + as: 'EventParticipants', + attributes: ['userId', 'teamId'], + include: [{ + model: User, + as: 'participants', + attributes: ['id', 'firstName', 'lastName'], + required: true + }] + } + ], + // Select the specific fields needed for the response mapping + attributes: [ + 'id', + 'teamName', + 'presentationLink', + 'githubLink', + 'projectName', + 'projectDescription' + ], + }); + } static async addParticipantToEvent(req, res){ const {userId, eventId} = req.body; @@ -123,6 +153,66 @@ class EventParticipantController{ }); } } + static async getTeamsByEvent(req, res) { + try { + // 1. Get eventId from query parameters + let { eventId } = req.query; + + if (eventId === 'undefined' || eventId === '') { + const activeEvent = await EventRepo.findActiveEvent(); + + if (!activeEvent) { + return res.status(404).json({ error: "No eventId provided and no active event found." }); + } + eventId = activeEvent.id; + } + + if (!eventId) { + return res.status(500).json({ error: "Internal error: Failed to determine event ID." }); + } + + // 2. Call a new repository function to get teams filtered by event + const teams = await TeamRepo.getTeamsByEvent(eventId); + + // 3. Map the data for the response + const teamData = teams.map(team => ({ + id: team.id, + teamName: team.teamName, + presentationLink: team.presentationLink || null, + githubLink: team.githubLink || null, + projectName: team.projectName || null, + projectDescription: team.projectDescription || null, + + // Map the team members list + participants: team.EventParticipants ? + team.EventParticipants.map(participant => { + const user = participant.participants; + + // Safety check remains valid + if (!user) { + console.warn(`Participant record in team ${team.id} is missing User details.`); + return 'Unknown User'; + } + + return { + id: user.id, + firstName: user.firstName, + lastName: user.lastName + }; + }) + : [] + })); + + res.status(200).json({ + message: `Successfully fetched teams for event ${eventId}`, + data: teamData + }); + + } catch (err) { + console.error('Error getting teams by event:', err); + res.status(500).json({ message: 'Error getting teams by event', error: err.message }); + } + } static async getUsersByEvent(req, res){ try { // 1. Get eventId from query parameters diff --git a/src/controllers/TeamController.js b/src/controllers/TeamController.js index 69198a2..0ec7257 100644 --- a/src/controllers/TeamController.js +++ b/src/controllers/TeamController.js @@ -77,8 +77,8 @@ class TeamController { const participants = await EventParticipantsRepo.findParticipantsByTeamId(teamId); const formattedParticipants = participants.map(p => ({ - id: p.userDetails.id, - name: `${p.userDetails.firstName} ${p.userDetails.lastName}` + id: p.participants.id, + name: `${p.participants.firstName} ${p.participants.lastName}` })); return { diff --git a/src/repository/config/Models.js b/src/repository/config/Models.js index 6c18f70..933792a 100644 --- a/src/repository/config/Models.js +++ b/src/repository/config/Models.js @@ -79,10 +79,10 @@ HackCategory.belongsTo(Event, { onDelete: 'CASCADE', }); -Team.hasMany(EventParticipant, { foreignKey: 'teamId' }); +Team.hasMany(EventParticipant, { foreignKey: 'teamId', as: 'EventParticipants' }); EventParticipant.belongsTo(Team, { foreignKey: 'teamId', as: 'EventParticipants' }); -EventParticipant.belongsTo(User, { foreignKey: 'userId', as: 'userDetails' }); +EventParticipant.belongsTo(User, { foreignKey: 'userId', as: 'participants', targetKey: 'id' }); User.hasMany(EventParticipant, { foreignKey: 'userId', as:'participant' }); /* HARDWARE/IMAGE ASSOCIATIONS */ diff --git a/src/repository/team/EventParticipantRepo.js b/src/repository/team/EventParticipantRepo.js index 649a930..75a4d04 100644 --- a/src/repository/team/EventParticipantRepo.js +++ b/src/repository/team/EventParticipantRepo.js @@ -7,7 +7,7 @@ class EventParticipantRepo { where: { teamId: teamId }, include: [{ model: User, - as: 'userDetails', + as: 'participants', attributes: ['id', 'firstName', 'lastName', 'isBanned'], where: { isBanned: { [Op.not]: true } @@ -22,7 +22,7 @@ class EventParticipantRepo { include: [{ model: User, - as: 'userDetails', + as: 'participants', attributes: [], where: { isBanned: { [Op.not]: true } @@ -69,7 +69,7 @@ class EventParticipantRepo { }, include: [{ model: User, - as: 'userDetails', + as: 'participants', attributes: ['id', 'firstName', 'lastName', 'email', 'checkIn', 'isBanned'] , where: { checkIn: 1, diff --git a/src/repository/team/TeamRepo.js b/src/repository/team/TeamRepo.js index ef2e72f..6ca65c8 100644 --- a/src/repository/team/TeamRepo.js +++ b/src/repository/team/TeamRepo.js @@ -1,4 +1,4 @@ -const { Team } = require('../config/Models'); +const { EventParticipant, User, Team } = require('../config/Models'); const TeamRepo = { // Method to create a new Team @@ -32,7 +32,7 @@ const TeamRepo = { return rowsUpdated; }, async delete(teamId){ - return Team.destroy({where: {id: teamId}}); + return Team.destroy({where: {id: teamId}}); }, async findProjectDetailsById(teamId) { try { @@ -73,6 +73,35 @@ const TeamRepo = { console.error('Repo error updating project details:', error); throw error; } + }, + async getTeamsByEvent(eventId) { + return await Team.findAll({ + where: { + eventId: eventId + }, + include: [ + { + model: EventParticipant, + as: 'EventParticipants', + attributes: ['userId', 'teamId'], + include: [{ + model: User, + as: 'participants', + attributes: ['id', 'firstName', 'lastName'], + required: true + }] + } + ], + // Select the specific fields needed for the response mapping + attributes: [ + 'id', + 'teamName', + 'presentationLink', + 'githubLink', + 'projectName', + 'projectDescription' + ], + }); } } diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index 5150ab4..8679ef2 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -5,7 +5,7 @@ const TeamController = require('../controllers/TeamController'); const EventParticipantController = require('../controllers/EventParticipantsController'); router.post('/create', TeamController.createTeam); -router.get('/all', TeamController.getAllTeams); +router.get('/all', EventParticipantController.getTeamsByEvent); router.get('/unassignedParticipants', EventParticipantController.getUnassignedParticipants); router.put('/unassign', EventParticipantController.unassignParticipant); router.put('/:id', TeamController.updateTeam); diff --git a/src/tests/team.test.js b/src/tests/team.test.js index f9eef67..e760225 100644 --- a/src/tests/team.test.js +++ b/src/tests/team.test.js @@ -33,12 +33,12 @@ const mockEventParticipantsData = [ { userId: MOCK_USER_ID_1, teamId: MOCK_TEAM_ID, - userDetails: mockParticipant1, + participants: mockParticipant1, }, { userId: MOCK_USER_ID_2, teamId: MOCK_TEAM_ID, - userDetails: mockParticipant2, + participants: mockParticipant2, }, ]; @@ -417,9 +417,9 @@ describe('EventParticipantController', () => { // -------------------------------------------------------------------------- describe('GET /teams/unassignedParticipants', () => { const mockUnassigned = [ - { userId: 301, teamId: null, eventId: 1, userDetails: { id: 301, firstName: 'A', lastName: 'Unassigned', email: 'a@example.com', checkIn: true, isBanned: false } }, - { userId: 302, teamId: null, eventId: 1, userDetails: { id: 302, firstName: 'B', lastName: 'Unassigned', email: 'b@example.com', checkIn: false, isBanned: 0 } }, - { userId: 303, teamId: null, eventId: 1, userDetails: { id: 303, firstName: 'C', lastName: 'Banned', email: 'c@example.com', checkIn: true, isBanned: true } }, // Should be filtered out + { userId: 301, teamId: null, eventId: 1, participants: { id: 301, firstName: 'A', lastName: 'Unassigned', email: 'a@example.com', checkIn: true, isBanned: false } }, + { userId: 302, teamId: null, eventId: 1, participants: { id: 302, firstName: 'B', lastName: 'Unassigned', email: 'b@example.com', checkIn: false, isBanned: 0 } }, + { userId: 303, teamId: null, eventId: 1, participants: { id: 303, firstName: 'C', lastName: 'Banned', email: 'c@example.com', checkIn: true, isBanned: true } }, // Should be filtered out ]; const expectedFormatted = [ { id: 301, firstName: 'A', lastName: 'Unassigned', email: 'a@example.com', checkIn: true, teamId: null },