Overview
The project report PDF generated by GET /api/projects/[id]/download currently shows team member names but no contact information. Add phone numbers for the project leader and all registered team members to make the report useful for coordinators and teachers who need to reach the team.
Current Behaviour
The PDF template renders:
- Project Title
- Project Leader (name only)
- Team Members (names only)
- Project Status
- Components
There is no contact information anywhere on the report.
What to Change
Data is already available in the route
The route already fetches everything needed (or very close to it):
const project = await prisma.project.findUnique({
where: { id },
include: {
leader: true,
members: { select: { userId: true } },
},
});
- Leader phone →
project.leader.phoneNumber is directly on the included leader object
- Member phones →
project.members gives [{ userId }, ...]; resolve each userId against User to get phoneNumber
Required query change
Extend the members include to pull full User data instead of just userId:
const project = await prisma.project.findUnique({
where: { id },
include: {
leader: true,
members: {
include: {
user: {
select: { id: true, name: true, phoneNumber: true, regId: true },
},
},
},
},
});
Then build the contact list:
const leaderContact = {
name: project.leader.name,
regId: project.leader.regId,
phone: project.leader.phoneNumber ?? 'N/A',
};
const memberContacts = project.members.map(m => ({
name: m.user.name,
regId: m.user.regId,
phone: m.user.phoneNumber ?? 'N/A',
}));
PDF Template Change
Add a Team Contact section to the generated PDF, below Team Members:
| Name |
Reg ID |
Role |
Phone |
| Aaditya Vinayak |
22CS001 |
Leader |
+91XXXXXXXXXX |
| Leena Vinayak |
22CS042 |
Member |
+91XXXXXXXXXX |
- If
phoneNumber is null for any user, render — or N/A (do not crash or leave blank)
- Phone numbers are stored in E.164 format (
+911234567890) — display as-is or format to local style, your call
- Keep the existing layout intact; insert the contact table after the current Team Members block
Edge Cases
- Legacy projects (no
ProjectMember rows): only the leader row will appear in the contact table — that's correct behaviour, no special handling needed
- Null phone numbers: some users may not have filled in
phoneNumber — always fall back gracefully, never render null or undefined
- Members include from new flow: this only works correctly once
ProjectMember rows exist (i.e. projects created after the registered team members feature lands). Old projects will show leader contact only.
Out of Scope
- No changes to any other route or page
- No schema changes —
phoneNumber already exists on User
- No changes to how phone numbers are collected or validated
Depends On
This issue depends on the ProjectMember join table being in place.
See: feat: Registered team members + member dashboard (read-only) with auth hardening
Member phone numbers will only appear for projects created via the new registered-member flow.
Verification Checklist
Overview
The project report PDF generated by
GET /api/projects/[id]/downloadcurrently shows team member names but no contact information. Add phone numbers for the project leader and all registered team members to make the report useful for coordinators and teachers who need to reach the team.Current Behaviour
The PDF template renders:
There is no contact information anywhere on the report.
What to Change
Data is already available in the route
The route already fetches everything needed (or very close to it):
project.leader.phoneNumberis directly on the includedleaderobjectproject.membersgives[{ userId }, ...]; resolve eachuserIdagainstUserto getphoneNumberRequired query change
Extend the
membersinclude to pull fullUserdata instead of justuserId:Then build the contact list:
PDF Template Change
Add a Team Contact section to the generated PDF, below Team Members:
phoneNumberisnullfor any user, render—orN/A(do not crash or leave blank)+911234567890) — display as-is or format to local style, your callEdge Cases
ProjectMemberrows): only the leader row will appear in the contact table — that's correct behaviour, no special handling neededphoneNumber— always fall back gracefully, never rendernullorundefinedProjectMemberrows exist (i.e. projects created after the registered team members feature lands). Old projects will show leader contact only.Out of Scope
phoneNumberalready exists onUserDepends On
Verification Checklist
phoneNumber: nullrender asN/Aor—, not blank or crashed403for unauthorized users (no regression from auth hardening)