Skip to content

Repository files navigation

GTA Portal

CI

A full-stack web app for managing Graduate Teaching Assistant hiring. Students apply for grader and lab-instructor positions; department admins review, sort and decide on applicants course by course.

Vue 3 + Vite on the front, NestJS + TypeScript on the back, MySQL 8 underneath, the whole thing running from a single docker compose up.

Screenshots

Home Application form
Home Apply
Student dashboard Admin review
Student Admin

Features

For students

  • Register and sign in with a real password, hashed with bcrypt
  • Submit an application for a specific course section, with client- and server-side validation on GPA, completed hours and every other field
  • Track the status of every application submitted — pending, accepted, rejected

For admins

  • Review all applications in one table, filtered by course
  • Sort by GPA, completed hours, or applicant name, ascending or descending
  • Accept or reject an application inline

Throughout

  • JWT authentication with role-based access control enforced server-side
  • Live, interactive API documentation at /api/docs
  • Keyboard-navigable forms: every input is labelled, errors are announced, and sortable table headers expose aria-sort

Tech stack

Layer Technology
Frontend Vue 3 (Composition API, <script setup>), Vite, Pinia, Vue Router, TypeScript, Bootstrap 5
Backend NestJS 11, TypeScript, TypeORM, Passport JWT, class-validator, Swagger
Database MySQL 8
Testing Jest + Supertest (API), Vitest + Vue Test Utils (web)
Infrastructure Docker Compose, nginx, GitHub Actions

Architecture

graph LR
  B[Browser] -->|HTTP| N[nginx<br/>serves the Vue build]
  N -->|proxies /api| A[NestJS API]
  A -->|TypeORM| D[(MySQL 8)]
Loading
erDiagram
  users ||--o| students : "profile"
  users ||--o{ applications : "submits"
  courses ||--o{ applications : "receives"
  users ||--o{ student_courses : "completed"
  courses ||--o{ student_courses : "taken by"

  users {
    int id PK
    char umkc_id UK
    varchar email UK
    char password_hash
    enum role
    varchar first_name
    varchar last_name
  }
  students {
    int user_id PK, FK
    varchar contact_no
    bool certified
  }
  courses {
    int id PK
    varchar course_no
    varchar course_name
    varchar section
    varchar instructor
  }
  applications {
    int id PK
    int user_id FK
    int course_id FK
    decimal gpa
    smallint hrs_completed
    enum curr_level
    enum position
    enum status
    datetime applied_at
  }
  student_courses {
    int user_id PK, FK
    int course_id PK, FK
    char grade
  }
Loading

Quick start

git clone https://github.com/UMKCGroupProject/UMKCDepartmentProject.git
cd UMKCDepartmentProject
docker compose up

Then open http://localhost:8080. The database is created and seeded on first boot, so you can log in immediately:

Role Email Password
Admin admin@example.edu Password123!
Student avery@example.edu Password123!

All seed data is fictional — invented names, courses and instructors on the reserved example.edu domain.

API

Interactive Swagger docs run at http://localhost:3000/api/docs. Sign in via POST /auth/login, then paste the returned token into Authorize.

Method Endpoint Access
POST /auth/register Public
POST /auth/login Public
GET /auth/me Authenticated
GET /courses Authenticated
POST /applications Authenticated
GET /applications/mine Authenticated
GET /applications?courseId=&sortBy=&order=&page=&limit= Admin
PATCH /applications/:id/status Admin

sortBy accepts gpa, hrsCompleted, lastName, firstName or appliedAt. It is an enum mapped to a column in code, so an unrecognised value is rejected with a 400 and never reaches the database.

Local development

Run the database in Docker and both apps on the host for hot reload.

# Database — run this from the repository root
docker run -d --name gta-db -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=rootpw -e MYSQL_DATABASE=gta_portal \
  -e MYSQL_USER=gta -e MYSQL_PASSWORD=gtapw \
  -v "$PWD/db:/docker-entrypoint-initdb.d:ro" mysql:8
# API — http://localhost:3000, docs at /api/docs
cd api
cp .env.example .env    # then set JWT_SECRET to 32+ characters
npm install
npm run start:dev
# Web — http://localhost:5173, in a second terminal
cd web
cp .env.example .env
npm install
npm run dev

The Vite dev server proxies /api to port 3000, so no CORS setup is needed.

Testing

cd api && npm test           # unit tests
cd api && npm run test:e2e   # API tests against a live database
cd web && npm test           # component, store and router tests

The API suite covers authentication, role enforcement, input validation and the sort-field whitelist. The web suite covers the auth store, router guards, and the form components.

Both workspaces also expose npm run lint, npm run typecheck and npm run format. CI runs all of these on every pull request, plus the API e2e suite against a MySQL service container and a Docker build that smoke-tests the running stack.

Project structure

api/                 NestJS API
  src/
    auth/            controller, service, JWT strategy, DTOs
    users/           user + student entities
    courses/         controller, service, entity
    applications/    controller, service, entity, DTOs
    common/          guards, decorators, exception filter
    config/          env validation
  test/              Supertest e2e specs
web/                 Vue 3 + Vite frontend
  src/
    api/             axios instance and interceptors
    stores/          Pinia auth store
    router/          routes and navigation guards
    layouts/         shared page shell
    components/      FormField, DataTable, header, footer
    views/           one component per route
  tests/             Vitest specs
db/                  schema and seed SQL, run on first boot
docs/screenshots/

Notes

  • All data is fictional. The seed uses invented names, courses and instructors on the reserved example.edu domain.
  • The demo credentials above are for the local seed only. JWT_SECRET is validated at boot to be at least 32 characters, and the compose file's value is a placeholder to be replaced anywhere real.

Contributing

See CONTRIBUTING.md for setup, the checks CI runs, and the conventions this project follows.

License

MIT — see LICENSE.

About

Graduate Teaching Assistant application portal — a 2022 undergrad team project being modernized to Vue 3 + Vite and a NestJS/TypeScript API.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages