CSC 317 — Group Project Milestone 4
A full-stack web application for managing and visualizing academic transcript data.
For detailed setup instructions, see SETUP.md.
Quick start:
- Clone repository:
git clone <repository-url> - Install dependencies:
npm install - Set up PostgreSQL database
- Copy
.env.exampleto.envand configure - Run migrations:
node db/reset.js - Start server:
node server.js
See .env.example for template. Required variables:
| Variable | Description | Example |
|---|---|---|
DB_HOST or PGHOST |
PostgreSQL host | localhost |
DB_PORT or PGPORT |
PostgreSQL port | 5432 |
DB_USER or PGUSER |
Database user | your_db_user |
DB_PASS or PGPASSWORD |
Database password | your_password |
DB_NAME or PGDATABASE |
Database name | academic_dashboard |
JWT_SECRET |
Secret key for JWT tokens | Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" |
PORT |
Server port (optional) | 3001 |
Note: The project supports both DB_* and PG* environment variable formats. Use one format consistently.
id(SERIAL PRIMARY KEY) - User IDemail(VARCHAR(255) UNIQUE NOT NULL) - User emailpassword_hash(VARCHAR(255) NOT NULL) - Hashed passwordname(VARCHAR(255)) - User's full name
id(SERIAL PRIMARY KEY) - Transcript IDuser_id(INTEGER UNIQUE NOT NULL) - Foreign key to users.iddegree(VARCHAR(255)) - Degree program
id(SERIAL PRIMARY KEY) - Term IDtranscript_id(INTEGER NOT NULL) - Foreign key to transcripts.idterm_code(VARCHAR(50)) - Term code (e.g., "SP2024")term_name(VARCHAR(255)) - Term nameterm_gpa(DECIMAL(3,2)) - Term GPAcredits(DECIMAL(5,2)) - Total creditsearned_credits(DECIMAL(5,2)) - Earned creditspoints(DECIMAL(6,2)) - GPA pointsis_planned(BOOLEAN DEFAULT FALSE) - Whether term is planned
id(SERIAL PRIMARY KEY) - Course IDterm_id(INTEGER NOT NULL) - Foreign key to terms.idcode(VARCHAR(50)) - Course codename(VARCHAR(255)) - Course nameunits(DECIMAL(4,2)) - Course unitsearned_units(DECIMAL(4,2)) - Earned unitsgrade(VARCHAR(10)) - Course gradepoints(DECIMAL(5,2)) - GPA points for course
users→transcripts(1:1) - One transcript per usertranscripts→terms(1:many) - Multiple terms per transcriptterms→courses(1:many) - Multiple courses per term
idx_transcripts_user_idontranscripts(user_id)idx_terms_transcript_idonterms(transcript_id)idx_courses_term_idoncourses(term_id)idx_terms_term_codeonterms(term_code)
| Method | Endpoint | Description | Auth Required | Request Body | Response |
|---|---|---|---|---|---|
| POST | /api/auth/register |
Register new user | No | { email, password, name? } |
{ success: true, data: { user, token } } |
| POST | /api/auth/login |
Login user | No | { email, password } |
{ success: true, data: { user, token } } |
| POST | /api/auth/logout |
Logout user | No | None | { success: true, message } |
| PUT | /api/auth/profile |
Update user profile | Yes | { email?, name?, password? } |
{ success: true, data: { user } } |
| PUT | /api/auth/password |
Change password | Yes | { currentPassword, newPassword } |
{ success: true, message } |
Authentication: Protected endpoints require Authorization: Bearer <token> header.
| Method | Endpoint | Description | Auth Required | Request Body | Response |
|---|---|---|---|---|---|
| GET | /api/transcripts |
Get user's transcript | Yes | None | { success: true, data: transcript | null } |
| POST | /api/transcripts |
Save new transcript | Yes | Transcript data object | { success: true, data: transcript } |
| PUT | /api/transcripts |
Update transcript | Yes | Transcript data object | { success: true, data: transcript } |
Transcript Data Structure:
{
"studentInfo": {
"name": "Student Name",
"degree": "Degree Program"
},
"terms": [
{
"term": "SP2024",
"termName": "Spring 2024",
"termGPA": 3.5,
"credits": 15.0,
"earnedCredits": 15.0,
"points": 52.5,
"isPlanned": false,
"courses": [
{
"code": "CSC 317",
"name": "Web Development",
"units": 3.0,
"earnedUnits": 3.0,
"grade": "A",
"points": 12.0
}
]
}
]
}-
User Authentication
- Registration with email validation
- Login with JWT tokens (4-hour expiry)
- Profile management (email, name)
- Secure password change
-
Transcript Management
- PDF parsing (client-side)
- Text file import
- JSON import
- Manual editing interface
- Data sanitization
- Chronological term sorting
-
Dashboard & Analytics
- Cumulative GPA calculation
- Semester-by-semester breakdown
- Interactive charts (GPA trends, grade distribution, credits)
- Course breakdown table
- Strength analysis
- On-going semester support
-
Data Visualization
- Customizable plot controls
- Responsive charts (Chart.js)
- Dynamic updates
-
User Interface
- Responsive design
- Protected routes
- Real-time notifications
- Loading states
- Error handling
-
PDF Parser: Basic parser may not handle all transcript formats; complex layouts may require manual entry.
-
Mobile Responsiveness: Chart visualizations may not be optimal on very small screens.
-
Error Recovery: No partial data recovery if PDF parsing fails.
-
Data Validation: Some edge cases in transcript formats may not be caught.
-
Performance: Large transcript files (100+ courses) may take longer to parse and render.
-
Accessibility: Some interactive elements could benefit from better keyboard navigation; screen reader support for charts could be enhanced.
A database backup file is included in the repository: backup-2025-11-19.tar
To export a fresh backup:
node export-database.jsTo import the included backup:
pg_restore -U your_db_user -d academic_dashboard backup-2025-11-19.tarOr for SQL format:
psql -U your_db_user -d academic_dashboard < backup.sql