diff --git a/app/api/dsoc/applications/route.ts b/app/api/dsoc/applications/route.ts index 4c6799d..90cecdf 100644 --- a/app/api/dsoc/applications/route.ts +++ b/app/api/dsoc/applications/route.ts @@ -43,7 +43,14 @@ export async function GET(request: NextRequest) { const mentorOnly = searchParams.get('mentor') === 'true'; const menteeOnly = searchParams.get('my') === 'true'; const menteeId = menteeOnly ? await getMenteeFromToken(request) : null; - + + if (menteeOnly && !menteeId) { + return NextResponse.json( + { success: false, error: 'Unauthorized' }, + { status: 401 } + ); + } + const query: any = {}; if (mentorOnly) { @@ -111,6 +118,14 @@ export async function POST(request: NextRequest) { const body = await request.json(); const { projectId, ...applicationData } = body; + + // Drop empty-string optional fields so mongoose doesn't try to cast them + // (empty string into a Date field throws CastError). + Object.keys(applicationData).forEach((key) => { + if (applicationData[key] === '' || applicationData[key] === null) { + delete applicationData[key]; + } + }); // Check if project exists and is open const project = await DSOCProject.findById(projectId); diff --git a/app/dsoc/mentee/dashboard/page.tsx b/app/dsoc/mentee/dashboard/page.tsx index 9b1e593..bf82795 100644 --- a/app/dsoc/mentee/dashboard/page.tsx +++ b/app/dsoc/mentee/dashboard/page.tsx @@ -20,6 +20,9 @@ interface Application { _id: string; status: string; createdAt: string; + mentorNotes?: string; + score?: number; + reviewedAt?: string; project: { _id: string; title: string; @@ -201,32 +204,63 @@ export default function MenteeDashboard() { ) : ( - applications.map((app) => ( -
-
-
-
- {getStatusIcon(app.status)} - - {app.status.replace('-', ' ')} - + applications.map((app) => { + const hasFeedback = + (app.status === 'accepted' || + app.status === 'rejected' || + app.status === 'waitlisted' || + app.status === 'under-review') && + (app.mentorNotes || typeof app.score === 'number'); + + return ( +
+
+
+
+ {getStatusIcon(app.status)} + + {app.status.replace('-', ' ')} + + {typeof app.score === 'number' && ( + + Score: {app.score}/100 + + )} +
+

{app.project.title}

+

{app.project.organization}

+

+ Applied on {new Date(app.createdAt).toLocaleDateString()} + {app.reviewedAt && ( + <> + {' • Reviewed '} + {new Date(app.reviewedAt).toLocaleDateString()} + + )} +

-

{app.project.title}

-

{app.project.organization}

-

- Applied on {new Date(app.createdAt).toLocaleDateString()} -

+ + + View Project +
- - - View Project - + + {hasFeedback && app.mentorNotes && ( +
+
+ Mentor Feedback +
+

+ {app.mentorNotes} +

+
+ )}
-
- )) + ); + }) )}
)} diff --git a/models/DSOCApplication.ts b/models/DSOCApplication.ts index dc10c88..b474d81 100644 --- a/models/DSOCApplication.ts +++ b/models/DSOCApplication.ts @@ -6,12 +6,19 @@ export interface IDSOCApplication extends Document { discordUsername: string; proposal: string; coverLetter?: string; - relevantExperience: string; whyThisProject: string; - availability: string; - expectedLearnings: string; + motivation?: string; + relevantExperience: string; + technicalSkills?: string; + githubProfile?: string; portfolioLinks: string[]; previousContributions?: string; + timeline?: string; + expectedLearnings: string; + challenges?: string; + availability: string; + timezone?: string; + startDate?: Date; status: 'pending' | 'under-review' | 'accepted' | 'rejected' | 'waitlisted' | 'withdrawn'; mentorNotes?: string; adminNotes?: string; @@ -48,19 +55,38 @@ const DSOCApplicationSchema = new Schema( type: String, trim: true, }, + whyThisProject: { + type: String, + required: [true, 'Why this project answer is required'], + trim: true, + }, + motivation: { + type: String, + trim: true, + }, relevantExperience: { type: String, required: [true, 'Relevant experience is required'], trim: true, }, - whyThisProject: { + technicalSkills: { type: String, - required: [true, 'Why this project answer is required'], trim: true, }, - availability: { + githubProfile: { + type: String, + trim: true, + }, + portfolioLinks: [{ + type: String, + trim: true, + }], + previousContributions: { + type: String, + trim: true, + }, + timeline: { type: String, - required: [true, 'Availability is required'], trim: true, }, expectedLearnings: { @@ -68,14 +94,22 @@ const DSOCApplicationSchema = new Schema( required: [true, 'Expected learnings is required'], trim: true, }, - portfolioLinks: [{ + challenges: { type: String, trim: true, - }], - previousContributions: { + }, + availability: { + type: String, + required: [true, 'Availability is required'], + trim: true, + }, + timezone: { type: String, trim: true, }, + startDate: { + type: Date, + }, status: { type: String, enum: ['pending', 'under-review', 'accepted', 'rejected', 'waitlisted', 'withdrawn'],