diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 3c3629e..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 9ca2e83..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "root": true, - "ignorePatterns": ["**/*"], - "plugins": ["@nx"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "@nx/enforce-module-boundaries": [ - "error", - { - "enforceBuildableLibDependency": true, - "allow": [], - "depConstraints": [ - { - "sourceTag": "*", - "onlyDependOnLibsWithTags": ["*"] - } - ] - } - ] - } - }, - { - "files": ["*.ts", "*.tsx"], - "extends": ["plugin:@nx/typescript"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "extends": ["plugin:@nx/javascript"], - "rules": {} - } - ] -} diff --git a/app/api/export/route.ts b/app/api/export/route.ts index 1d473af..ed242ba 100644 --- a/app/api/export/route.ts +++ b/app/api/export/route.ts @@ -28,6 +28,8 @@ export async function GET(request: NextRequest) { 'Diversity, Equity, & Inclusion', 'Conflict Situation', 'Campaign Blurb', + 'Boston Campus Full Term', + 'Boston Campus Explanation', 'Created At' ]; @@ -51,6 +53,8 @@ export async function GET(request: NextRequest) { app.diversityEquityInclusionLongAnswer || '', app.conflictSituationLongAnswer || '', app.campaignBlurb || '', + app.bostonCampus ? 'Yes' : 'No', + app.bostonCampusExplanation || '', app.createdAt?.toISOString() || '' ]); @@ -66,7 +70,9 @@ export async function GET(request: NextRequest) { // Build CSV content const csvContent = [ headers.map(escapeCSVField).join(','), - ...rows.map((row) => row.map(escapeCSVField).join(',')) + ...rows.map((row: (string | null | undefined)[]) => + row.map(escapeCSVField).join(',') + ) ].join('\n'); const filename = `applicants_${new Date().toISOString().split('T')[0]}.csv`; diff --git a/app/applications/application-form.tsx b/app/applications/application-form.tsx index 6b26f8e..886e0e8 100644 --- a/app/applications/application-form.tsx +++ b/app/applications/application-form.tsx @@ -75,6 +75,10 @@ const applicationSchema = z campaignBlurb: z .string() .min(50, 'Please provide a detailed response (at least 50 characters)'), + bostonCampus: z.boolean({ + error: 'Please indicate if you will be on the Boston campus', + }), + bostonCampusExplanation: z.string().optional(), }) .refine( (data) => { @@ -85,6 +89,19 @@ const applicationSchema = z message: 'Constituency must be one of the selected colleges', path: ['constituency'], }, + ) + .refine( + (data) => { + // If not on Boston campus, explanation is required + if (data.bostonCampus === false) { + return data.bostonCampusExplanation && data.bostonCampusExplanation.trim().length > 0; + } + return true; + }, + { + message: 'Please explain your situation if you will not be on the Boston campus for the entirety of your term', + path: ['bostonCampusExplanation'], + }, ); type ApplicationFormData = z.infer; @@ -133,11 +150,13 @@ export default function ApplicationForm({ diversityEquityInclusionLongAnswer: '', conflictSituationLongAnswer: '', campaignBlurb: '', + bostonCampusExplanation: '', }, }); const colleges = watch('college'); const constituency = watch('constituency'); + const bostonCampus = watch('bostonCampus'); // Auto-select constituency if only one college is selected, clear if invalid useEffect(() => { @@ -795,6 +814,65 @@ export default function ApplicationForm({

)} + +
+ +
+ + +
+ {errors.bostonCampus && ( +

+ {errors.bostonCampus.message} +

+ )} +
+ + {bostonCampus === false && ( +
+ +