Build full-stack scholarship discovery web application - #1
Merged
Conversation
Agent-Logs-Url: https://github.com/pltcinstruct06/scholarship/sessions/0d2872cd-6301-4380-96e9-6114857528e8 Co-authored-by: pltcinstruct06 <159825927+pltcinstruct06@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Develop web application for scholarship discovery using NLP and ML
Build full-stack scholarship discovery web application
May 6, 2026
pltcinstruct06
marked this pull request as ready for review
July 30, 2026 03:44
There was a problem hiding this comment.
Pull request overview
Greenfield implementation of a full-stack “ScholarFinder” scholarship discovery platform, introducing a Node/Express/MongoDB REST API (auth, scholarship search, applications, recommendations) and a React SPA frontend (search, detail, auth, dashboard, profile).
Changes:
- Added backend API with MongoDB models, JWT auth, scholarship search/filtering, application tracking, recommendations, and seed data.
- Added React frontend with routing, auth context, API client, and core pages (Home/Search/Detail/Dashboard/Profile/Auth).
- Added initial Jest/Supertest backend tests and basic CRA frontend test setup, plus project documentation.
Reviewed changes
Copilot reviewed 56 out of 63 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Project-level documentation for features, setup, and API endpoints |
| frontend/src/setupTests.js | Jest DOM setup for frontend tests |
| frontend/src/services/api.js | Axios client + auth interceptors + API wrappers |
| frontend/src/reportWebVitals.js | CRA web vitals helper |
| frontend/src/pages/Search.js | Scholarship search UI with filters + pagination |
| frontend/src/pages/Search.css | Styling for Search page |
| frontend/src/pages/ScholarshipDetail.js | Scholarship detail UI + track/save actions |
| frontend/src/pages/ScholarshipDetail.css | Styling for Scholarship detail page |
| frontend/src/pages/Register.js | Registration page and profile capture |
| frontend/src/pages/Profile.js | Profile edit form and completeness UI |
| frontend/src/pages/Profile.css | Styling for Profile page |
| frontend/src/pages/Login.js | Login page |
| frontend/src/pages/Home.js | Home page with featured + recommendations sections |
| frontend/src/pages/Home.css | Styling for Home page |
| frontend/src/pages/Dashboard.js | Dashboard (applications/saved/recommendations tabs) |
| frontend/src/pages/Dashboard.css | Styling for Dashboard page |
| frontend/src/pages/Auth.css | Shared styling for Login/Register pages |
| frontend/src/logo.svg | CRA logo asset |
| frontend/src/index.js | React entry point + routing mount |
| frontend/src/index.css | Global base styles |
| frontend/src/context/AuthContext.js | Auth context with token persistence and /me fetch |
| frontend/src/components/Spinner.js | Loading spinner component |
| frontend/src/components/Spinner.css | Spinner styling |
| frontend/src/components/ScholarshipCard.js | Scholarship card UI used across pages |
| frontend/src/components/ScholarshipCard.css | Scholarship card styling |
| frontend/src/components/Navbar.js | Navigation bar with auth-aware links |
| frontend/src/components/Navbar.css | Navbar styling + responsive menu |
| frontend/src/App.test.js | Basic frontend render test |
| frontend/src/App.js | App routes + Private/Public route guards |
| frontend/src/App.css | Global app styles |
| frontend/README.md | Default CRA README (project subdir) |
| frontend/public/robots.txt | Robots file |
| frontend/public/manifest.json | PWA manifest metadata |
| frontend/public/index.html | HTML template + meta tags |
| frontend/package.json | Frontend dependencies and scripts |
| frontend/.gitignore | Frontend ignore rules |
| frontend/.env.example | Frontend env example |
| backend/src/services/seeder.js | Seed script inserting sample scholarships |
| backend/src/routes/scholarships.js | Scholarship API routes (public + admin) |
| backend/src/routes/recommendations.js | Recommendation API route |
| backend/src/routes/auth.js | Auth routes + validation |
| backend/src/routes/applications.js | Application tracker routes |
| backend/src/models/User.js | User model (profile, saved, search history) |
| backend/src/models/Scholarship.js | Scholarship model + indexes (text + filters) |
| backend/src/models/Application.js | Application model + unique user+scholarship index |
| backend/src/middleware/errorHandler.js | Centralized error handling |
| backend/src/middleware/auth.js | JWT protect + adminOnly middleware |
| backend/src/index.js | Express app setup (helmet/cors/rate limit/routes) |
| backend/src/controllers/scholarshipController.js | Scholarship list/detail/admin CRUD + filtering |
| backend/src/controllers/recommendationController.js | Recommendation scoring and ranking |
| backend/src/controllers/authController.js | Register/login/me/profile/save toggle |
| backend/src/controllers/applicationController.js | Application CRUD and status updates |
| backend/src/config/database.js | MongoDB connection helper |
| backend/src/tests/setup.js | Backend test env setup |
| backend/src/tests/api.test.js | Backend API tests with mocked models |
| backend/package.json | Backend dependencies/scripts + Jest config |
| backend/.env.example | Backend env example |
| .gitignore | Repo-level ignore rules |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+106
to
+110
| // Log search to user history if authenticated | ||
| if (req.user && (search || major || location)) { | ||
| User.findByIdAndUpdate(req.user._id, { | ||
| $push: { | ||
| searchHistory: { |
Comment on lines
+43
to
+47
| query.$or = [ | ||
| ...(query.$or || []), | ||
| { 'location.states': { $regex: state, $options: 'i' } }, | ||
| { 'location.type': 'national' }, | ||
| ]; |
Comment on lines
+18
to
+24
| const { name, email, password } = req.body; | ||
| const existing = await User.findOne({ email: email.toLowerCase() }); | ||
| if (existing) { | ||
| return res.status(409).json({ success: false, message: 'Email already registered.' }); | ||
| } | ||
|
|
||
| const user = await User.create({ name, email, password }); |
Comment on lines
+53
to
+60
| // GPA | ||
| if (p.gpa != null && s.eligibility && s.eligibility.minGpa) { | ||
| if (p.gpa >= s.eligibility.minGpa) { | ||
| score += 10; | ||
| } | ||
| } else { | ||
| score += 5; // no GPA requirement is a slight positive | ||
| } |
Comment on lines
+27
to
+40
| const ScholarshipCard = ({ scholarship, onSave, savedIds = [] }) => { | ||
| const isSaved = savedIds.includes(scholarship._id); | ||
|
|
||
| return ( | ||
| <div className={`scholarship-card ${scholarship.featured ? 'featured' : ''}`}> | ||
| {scholarship.featured && <span className="badge-featured">⭐ Featured</span>} | ||
| <div className="card-header"> | ||
| <h3 className="card-title"> | ||
| <Link to={`/scholarships/${scholarship._id}`}>{scholarship.title}</Link> | ||
| </h3> | ||
| <p className="card-provider">{scholarship.provider}</p> | ||
| </div> | ||
| <p className="card-desc">{scholarship.description.slice(0, 140)}…</p> | ||
| <div className="card-meta"> |
Comment on lines
+44
to
+47
| if (!user) { | ||
| navigate('/login'); | ||
| return null; | ||
| } |
Comment on lines
+8
to
+15
| const formatAmount = (amount) => { | ||
| if (!amount) return 'Varies'; | ||
| const { min, max, renewable } = amount; | ||
| if (!min && !max) return 'Varies'; | ||
| let str = min === max ? `$${min.toLocaleString()}` : `$${(min || 0).toLocaleString()} – $${(max || 0).toLocaleString()}`; | ||
| if (renewable) str += ' (Renewable)'; | ||
| return str; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Greenfield implementation of a scholarship discovery platform: search/filter scholarships by major and geography, track applications, and receive profile-based recommendations.
Backend — Node.js / Express / MongoDB
User(profile, saved scholarships, search history),Scholarship(MongoDB text index on title/description/majors/tags with per-field weights),Application(unique per user+scholarship, status FSM)GET /me, profile update, save/unsave toggleinterested → in_progress → submitted → awarded / rejected / withdrawnexpress-rate-limit(100 req / 15 min),express-validatoron auth routesFrontend — React / React Router v6 / Axios
localStorage, request interceptor attachesAuthorizationheader, 401 interceptor clears token and redirectsRecommendation scoring example
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
fastdl.mongodb.org/usr/local/bin/node node ./postinstall.js(dns block)/usr/local/bin/node node /home/REDACTED/work/scholarship/scholarship/backend/node_modules/.bin/jest --testEnvironment=node --runInBand --forceExit(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt