diff --git a/backend/package-lock.json b/backend/package-lock.json
index 7ecd772..48611eb 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -1263,6 +1263,7 @@
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.8.tgz",
"integrity": "sha512-WiE9uCGRLUnShdjb9iP20sA3ToWrBbNXr14/N5mow7Nls9dmKgfGaGX5cynLvrltxq2OrDLh1VDNaUgsnS/k/g==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@firebase/component": "0.7.0",
"@firebase/logger": "0.5.0",
@@ -1329,6 +1330,7 @@
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.8.tgz",
"integrity": "sha512-4De6SUZ36zozl9kh5rZSxKWULpgty27rMzZ6x+xkoo7+NWyhWyFdsdvhFsWhTw/9GGj0wXIcbTjwHYCUIUuHyg==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@firebase/app": "0.14.8",
"@firebase/component": "0.7.0",
@@ -1344,7 +1346,8 @@
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
- "license": "Apache-2.0"
+ "license": "Apache-2.0",
+ "peer": true
},
"node_modules/@firebase/auth": {
"version": "1.12.0",
@@ -1795,6 +1798,7 @@
"integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==",
"hasInstallScript": true,
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"tslib": "^2.1.0"
},
@@ -2943,6 +2947,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz",
"integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -3040,6 +3045,7 @@
"integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "6.21.0",
@@ -3076,6 +3082,7 @@
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
"dev": true,
"license": "BSD-2-Clause",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/types": "6.21.0",
@@ -3281,7 +3288,8 @@
"version": "14.18.33",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz",
"integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@vercel/node/node_modules/ts-node": {
"version": "10.9.1",
@@ -3331,6 +3339,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3380,6 +3389,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4961,6 +4971,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -5126,6 +5137,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -9134,6 +9146,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/backend/seed-data/seed-students.ts b/backend/seed-data/seed-students.ts
index 9f290cb..8a0845f 100644
--- a/backend/seed-data/seed-students.ts
+++ b/backend/seed-data/seed-students.ts
@@ -22,6 +22,7 @@ const preservedUserIds: string[] = [];
const sampleStudents = [
{
+ _id: "student_001",
email: "alex.chen@university.edu",
name: "Alex Chen",
profilePicture:
@@ -38,8 +39,10 @@ const sampleStudents = [
organizations: ["Computer Science Society"],
specializations: ["Web Systems"],
school: "Tech University",
+ shareProfile: true,
},
{
+ _id: "student_002",
email: "maya.patel@state.edu",
name: "Maya Patel",
profilePicture:
@@ -56,8 +59,10 @@ const sampleStudents = [
organizations: ["Women in STEM"],
specializations: ["Artificial Intelligence"],
school: "State University",
+ shareProfile: true,
},
{
+ _id: "student_003",
email: "jordan.smith@college.edu",
name: "Jordan Smith",
profilePicture:
@@ -74,8 +79,10 @@ const sampleStudents = [
organizations: ["Cyber Defense Club"],
specializations: ["Infrastructure"],
school: "Institute of Technology",
+ shareProfile: false,
},
{
+ _id: "student_004",
email: "liam.nguyen@uni.edu",
name: "Liam Nguyen",
profilePicture:
@@ -92,8 +99,10 @@ const sampleStudents = [
organizations: ["Game Dev Guild"],
specializations: ["Interactive Media"],
school: "Academy of Arts",
+ shareProfile: true,
},
{
+ _id: "student_005",
email: "sarah.kim@global.edu",
name: "Sarah Kim",
profilePicture:
@@ -110,8 +119,10 @@ const sampleStudents = [
organizations: ["Finance Association"],
specializations: ["Econometrics"],
school: "Global Business School",
+ shareProfile: false,
},
{
+ _id: "student_006",
email: "oscar.rodriguez@tech.edu",
name: "Oscar Rodriguez",
profilePicture:
@@ -128,8 +139,10 @@ const sampleStudents = [
organizations: ["Design Collective"],
specializations: ["User Experience"],
school: "Design Institute",
+ shareProfile: true,
},
{
+ _id: "student_007",
email: "chloe.wilson@state.edu",
name: "Chloe Wilson",
profilePicture: "https://images.unsplash.com/photo-1544005313-94ddf0286df2",
@@ -145,8 +158,10 @@ const sampleStudents = [
organizations: ["Cloud Computing Group"],
specializations: ["Distrubuted Systems"],
school: "Western University",
+ shareProfile: true,
},
{
+ _id: "student_008",
email: "ethan.brown@poly.edu",
name: "Ethan Brown",
profilePicture:
@@ -163,8 +178,10 @@ const sampleStudents = [
organizations: ["IEEE Student Branch"],
specializations: ["Microprocessors"],
school: "Polytechnic University",
+ shareProfile: false,
},
{
+ _id: "student_009",
email: "isabella.white@uni.edu",
name: "Isabella White",
profilePicture: "https://images.unsplash.com/photo-1554151228-14d9def656e4",
@@ -180,8 +197,10 @@ const sampleStudents = [
organizations: ["App Developers Club"],
specializations: ["Interface Design"],
school: "Central University",
+ shareProfile: true,
},
{
+ _id: "student_10",
email: "noah.davis@college.edu",
name: "Noah Davis",
profilePicture: "https://images.unsplash.com/photo-1552058544-f2b08422138a",
@@ -197,6 +216,7 @@ const sampleStudents = [
organizations: ["MIS Society"],
specializations: ["Information Security"],
school: "Business College",
+ shareProfile: false,
},
];
@@ -232,4 +252,4 @@ async function seedStudents() {
}
}
-seedStudents();
+seedStudents();
\ No newline at end of file
diff --git a/backend/src/controllers/userController.ts b/backend/src/controllers/userController.ts
index 84b1d0a..3780312 100644
--- a/backend/src/controllers/userController.ts
+++ b/backend/src/controllers/userController.ts
@@ -324,6 +324,43 @@ export const getOpenAlumni = asyncHandler(async (req, res, next) => {
});
});
+// @desc Get students willing to share profile
+// @route GET /api/users/student
+// @access Private
+export const getOpenStudents = asyncHandler(async (req, res, next) => {
+ const errors = validationResult(req);
+ if (!errors.isEmpty()) {
+ return next(createHttpError(400, validationErrorParser(errors)));
+ }
+
+ const { page, perPage } = matchedData(req, {
+ locations: ["query"],
+ });
+
+ const dbQuery = User.find({
+ type: UserType.Student,
+ });
+
+ // ensure count and paginate do not conflict
+ const countQuery = dbQuery.clone();
+
+ // count total results, populate company, and paginate in parallel
+ const [total, users] = await Promise.all([
+ countQuery.countDocuments(),
+ dbQuery
+ .skip(page * perPage)
+ .limit(perPage)
+ .exec(),
+ ]);
+
+ res.status(200).json({
+ page,
+ perPage,
+ total,
+ data: users,
+ });
+});
+
export const getAlumniSimilarities = asyncHandler(async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
diff --git a/backend/src/routes/userRoutes.ts b/backend/src/routes/userRoutes.ts
index 96e61aa..fe3220a 100644
--- a/backend/src/routes/userRoutes.ts
+++ b/backend/src/routes/userRoutes.ts
@@ -13,6 +13,12 @@ userRouter.get(
userController.getOpenAlumni,
);
+userRouter.get(
+ "/student",
+ userValidator.getOpenStudentsValidator,
+ userController.getOpenStudents,
+);
+
userRouter.get(
"/:id",
userValidator.getUservalidator,
diff --git a/backend/src/validators/userValidator.ts b/backend/src/validators/userValidator.ts
index c1033c4..a96e259 100644
--- a/backend/src/validators/userValidator.ts
+++ b/backend/src/validators/userValidator.ts
@@ -298,6 +298,14 @@ export const getOpenAlumniValidator = [
validateIndustry,
];
+export const getOpenStudentsValidator = [
+ validatePage,
+ validatePerPage,
+ validateQuery,
+ validateMajor,
+ validateClassLevel,
+];
+
export const getSimilaritiesValidator = [
param("studentId")
.isString()
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 8f0c6e1..46c438f 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -99,6 +99,7 @@
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -919,6 +920,7 @@
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.13.2.tgz",
"integrity": "sha512-jwtMmJa1BXXDCiDx1vC6SFN/+HfYG53UkfJa6qeN5ogvOunzbFDO3wISZy5n9xgYFUrEP6M7e8EG++riHNTv9w==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@firebase/component": "0.6.18",
"@firebase/logger": "0.4.4",
@@ -985,6 +987,7 @@
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.4.2.tgz",
"integrity": "sha512-LssbyKHlwLeiV8GBATyOyjmHcMpX/tFjzRUCS1jnwGAew1VsBB4fJowyS5Ud5LdFbYpJeS+IQoC+RQxpK7eH3Q==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@firebase/app": "0.13.2",
"@firebase/component": "0.6.18",
@@ -1000,7 +1003,8 @@
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
- "license": "Apache-2.0"
+ "license": "Apache-2.0",
+ "peer": true
},
"node_modules/@firebase/auth-compat": {
"version": "0.5.28",
@@ -1457,6 +1461,7 @@
"integrity": "sha512-zGlBn/9Dnya5ta9bX/fgEoNC3Cp8s6h+uYPYaDieZsFOAdHP/ExzQ/eaDgxD3GOROdPkLKpvKY0iIzr9adle0w==",
"hasInstallScript": true,
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"tslib": "^2.1.0"
},
@@ -2168,8 +2173,7 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -2587,6 +2591,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
"integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
@@ -2597,6 +2602,7 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"license": "MIT",
+ "peer": true,
"peerDependencies": {
"@types/react": "^18.0.0"
}
@@ -2670,6 +2676,7 @@
"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.54.0",
"@typescript-eslint/types": "8.54.0",
@@ -3061,6 +3068,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3476,6 +3484,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -4138,6 +4147,7 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -4728,6 +4738,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -6307,6 +6318,7 @@
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"devOptional": true,
"license": "MIT",
+ "peer": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
@@ -6530,7 +6542,6 @@
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"license": "MIT",
- "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -7064,6 +7075,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -7411,6 +7423,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -7423,6 +7436,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -7452,6 +7466,7 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
@@ -7598,7 +7613,8 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/redux-thunk": {
"version": "3.1.0",
@@ -8473,6 +8489,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -8661,6 +8678,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -8802,6 +8820,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -8915,6 +8934,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index b546b12..bb9e509 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -8,7 +8,9 @@ import SavedApplications from "./pages/SavedApplications";
import Companies from "./pages/Companies";
import CompanyProfile from "./pages/Company";
import AlumniProfile from "./pages/Alumni";
+import StudentProfile from "./pages/Student";
import Connect from "./pages/Connect";
+import Students from "./pages/Students";
import Sandbox from "./pages/Sandbox";
import Profile from "./pages/Profile";
import Analytics from "./pages/Analytics";
@@ -24,7 +26,9 @@ function App() {
No alumni currently fit your query. Edit your Industry type to find alumni in a different category. No users currently fit your query. Edit your filters to find users in a different category.
+ ) : (
+
{student.name}
+
+ Contact Information
+
+
+
+ ) : (
+ {data.name.charAt(0)}
+ )}
+
{data.name}
+
-
+ {user.shareProfile + ? "Visible to students" + : "Not shared with students"} +
+{student.name}
+{student.email}
++ {student.phoneNumber || "Not provided"} +
+Not provided
+ )} ++ {student.major || "Not specified"} +
++ {student.classLevel + ? student.classLevel.charAt(0).toUpperCase() + + student.classLevel.slice(1).toLowerCase() + : "Not specified"} +
++ {student.shareProfile + ? "Visible to students" + : "Not shared with students"} +
++ {student.school + ? student.school.charAt(0).toUpperCase() + + student.school.slice(1).toLowerCase() + : "Not specified"} +
+Not specified
+ )} +Not specified
+ )} +Not specified
+ )} +Not specified
+ )} +Not specified
+ )} +{similaritySummary}
+ )} ++ Generate a personalized outreach email to {student?.name} based on your shared interests. +
+ +Connect with UCSD students on Opportune!
+