A full-stack course management and lookup system built for RIC.
RICCourseList provides a web interface for browsing courses and students, searching and sorting course information, viewing course attendees, and managing favorite courses.
-
📚 Course List
- Browse all available courses
- Search by course code or name
- Case-sensitive / case-insensitive search
- Search by course code only
- Sort courses by code
- Pagination
-
👨🎓 Student List
- Browse students
- Search and view student information
- View courses associated with a student
-
👥 Course Attendees
- View students enrolled in a selected course
- Navigate between courses and their attendees
- React
- TypeScript
- Vite
- Go
- Gin
- pgx
- PostgreSQL
- VS Code
- Git / GitHub
- Replit
- ChatGPT
RICCourseList follows a simple full-stack architecture:
┌──────────────────────┐
│ React / TS │
│ Frontend │
└──────────┬───────────┘
│ HTTP / JSON
▼
┌──────────────────────┐
│ Go + Gin │
│ API │
└──────────┬───────────┘
│ SQL
▼
┌──────────────────────┐
│ PostgreSQL │
│ Database │
└──────────────────────┘
The frontend communicates with the backend through REST APIs. The backend handles request validation, query construction, pagination, and database access.
The current database uses PostgreSQL.
Main entities include:
students
│
│ many-to-many
▼
student_courses
▲
│ many-to-many
│
courses
The student_courses table represents the relationship between students and courses.
Primary keys and foreign-key constraints are used to maintain data integrity.
The backend provides RESTful APIs under the /api prefix.
All list endpoints support pagination through:
current— current page numberpage_size— number of items per pageascending— whether the results are sorted in ascending order
Successful responses follow the general structure:
{
"meta": {
"total_count": 0,
"number_of_pages": 0
},
"body": []
}GET /api/coursesQuery parameters:
| Parameter | Type | Description |
|---|---|---|
search |
string | Search keyword |
current |
integer | Current page number |
page_size |
integer | Number of courses per page |
case_sensitive |
boolean | Whether the search is case-sensitive |
code_only |
boolean | Search only within course codes |
ascending |
boolean | Sort courses in ascending or descending order |
Example:
GET /api/courses?search=COMP¤t=1&page_size=10&case_sensitive=false&code_only=false&ascending=trueGET /api/studentsQuery parameters:
| Parameter | Type | Description |
|---|---|---|
name |
string | Search keyword for student names |
current |
integer | Current page number |
page_size |
integer | Number of students per page |
ascending |
boolean | Sort students in ascending or descending order |
Example:
GET /api/students?name=Jason¤t=1&page_size=10&ascending=trueGET /api/courses/:id/attendeesReturns the students enrolled in a specific course.
Path parameters:
| Parameter | Type | Description |
|---|---|---|
id |
integer | Course ID |
Query parameters:
| Parameter | Type | Description |
|---|---|---|
current |
integer | Current page number |
page_size |
integer | Number of students per page |
ascending |
boolean | Sort students in ascending or descending order |
Example:
GET /api/courses/1/attendees?current=1&page_size=10&ascending=trueGET /api/students/:id/attended_classesReturns the courses attended by a specific student.
Path parameters:
| Parameter | Type | Description |
|---|---|---|
id |
integer | Student ID |
Query parameters:
| Parameter | Type | Description |
|---|---|---|
current |
integer | Current page number |
page_size |
integer | Number of courses per page |
ascending |
boolean | Sort courses in ascending or descending order |
Example:
GET /api/students/1/attended_classes?current=1&page_size=10&ascending=trueInvalid request parameters return HTTP 400 Bad Request with an error message.
Example:
{
"error": "Invalid course ID"
}Internal database errors return HTTP 500 Internal Server Error.
{
"error": "..."
}The backend validates and sanitizes query parameters before constructing SQL queries.
For example:
- Page numbers must be positive.
- Page sizes are restricted to a reasonable range.
- Search strings are length-limited.
%,_, and\are escaped when used in SQLLIKEqueries.- Sorting fields and ordering are explicitly controlled.
- Pagination uses SQL
LIMITandOFFSET.
This prevents malformed requests from reaching the database and avoids treating user-provided search characters as unintended SQL pattern operators.
Guo Zichen (Jason)
GitHub: @JasonG25


