Files
hope-events/backend/src/controllers/formController.js
T
joshuaandClaude Opus 5.5 344f260011 Campus-scoped staff: schema, campusScope helper, route test, first 79 routes
UserCampusScope relation and audit action; scopeEvent/scopeList/unscopedOnly/
campusIndependent/scopeBroadcast markers; tests/campusScopeRoutes.test.js
(still failing: events, payments, registrations, scan locks, tickets left).
Can't delete a campus that has scoped staff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:28:30 +02:00

65 lines
2.4 KiB
JavaScript

const prisma = require('../config/db');
// @desc List submitted form responses with optional filters
// @route GET /api/forms/responses
// @access Private/Staff (admin, supervisor, staff)
const listFormResponses = async (req, res) => {
try {
const { eventId, userId, registrationId, limit, cursor } = req.query;
// Build where clause
const where = {};
if (registrationId) {
where.registrationId = String(registrationId);
}
// For eventId/userId we filter through the related registration
const registrationFilter = {};
if (eventId) registrationFilter.eventId = String(eventId);
if (userId) registrationFilter.userId = String(userId);
Object.assign(registrationFilter, await require('../utils/campusScope').listWhere(req, 'event'));
if (Object.keys(registrationFilter).length > 0) {
// Prisma relation filter requires `is` wrapper
where.registration = { is: registrationFilter };
}
// Basic pagination (optional)
const take = Math.min(Math.max(parseInt(limit || '50', 10) || 50, 1), 200);
const cursorClause = cursor ? { id: String(cursor) } : undefined;
const responses = await prisma.formResponse.findMany({
where,
include: {
registration: {
include: {
user: { select: { id: true, name: true, email: true } },
event: { select: { id: true, title: true } },
}
},
answers: { include: { field: true } },
},
orderBy: { createdAt: 'desc' },
take,
...(cursorClause ? { skip: 1, cursor: cursorClause } : {}),
});
const nextCursor = responses.length === take ? responses[responses.length - 1].id : null;
// The first page of a list (not one registration's own form, nor the next pages of the
// same list) is logged as a bulk view of form answers.
if (!registrationId && !cursor && responses.length) {
require('../utils/accessLog').logDataAccess(req, {
action: 'form_responses',
what: `Attendee form answers${responses[0].registration?.event && eventId ? ` — ${responses[0].registration.event.title}` : ''}`,
eventId: eventId ? String(eventId) : null,
records: responses.length,
});
}
res.json({ items: responses, nextCursor });
} catch (error) {
res.status(400).json({ message: error.message });
}
};
module.exports = { listFormResponses };