Overview

The Express server runs on http://localhost:3000 and provides REST endpoints for curriculum calendar data.

# Start the server
cd E:\Lucas\Personal-Productivity
npm start

Base URL: http://localhost:3000/api

GET /api/health

Check server and database status.

Request

GET /api/health

Response

{
  "status": "ok",
  "database": "connected",
  "timestamp": "2025-11-28T10:30:00.000Z"
}

Error Response

{
  "status": "error",
  "database": "disconnected",
  "error": "Connection refused"
}

GET /api/weeks

Get all 24 school weeks.

Request

GET /api/weeks

Response

[
  {
    "id": 1,
    "week_number": 1,
    "start_date": "2025-08-18",
    "end_date": "2025-08-22",
    "theme": "Back to School",
    "goals": "Establish routines, review basics"
  },
  {
    "id": 2,
    "week_number": 2,
    "start_date": "2025-08-25",
    "end_date": "2025-08-29",
    "theme": "Building Foundations",
    "goals": "..."
  }
  // ... 24 weeks total
]

GET /api/weeks/:weekNumber/assignments

Get all assignments for a specific week.

Request

GET /api/weeks/1/assignments

Response

[
  {
    "id": 1,
    "week_id": 1,
    "subject_id": 1,
    "day_of_week": 1,
    "title": "Place Value Review",
    "description": "Review place value concepts...",
    "duration_minutes": 30,
    "assignment_type": "lesson",
    "sequence_order": 1,
    "resource_id": 1,
    "subject": {
      "id": 1,
      "name": "Math",
      "color": "#3b82f6",
      "emoji": "🔢"
    },
    "resource": {
      "id": 1,
      "name": "Saxon Math 5/4",
      "type": "textbook"
    }
  },
  // ... more assignments
]

Query Parameters

day Filter by day (1-5, Monday-Friday)
subject Filter by subject ID
GET /api/weeks/1/assignments?day=1
GET /api/weeks/1/assignments?subject=1

GET /api/subjects

Get all subjects with colors and emojis.

Request

GET /api/subjects

Response

[
  { "id": 1, "name": "Math", "color": "#3b82f6", "emoji": "🔢" },
  { "id": 2, "name": "Writing", "color": "#eab308", "emoji": "✍️" },
  { "id": 3, "name": "Reading", "color": "#22c55e", "emoji": "📖" },
  { "id": 4, "name": "Science", "color": "#a855f7", "emoji": "🔬" },
  { "id": 5, "name": "Spelling", "color": "#f97316", "emoji": "📝" },
  { "id": 6, "name": "History", "color": "#ec4899", "emoji": "🏛️" },
  { "id": 7, "name": "Art", "color": "#14b8a6", "emoji": "🎨" },
  { "id": 8, "name": "Music", "color": "#6366f1", "emoji": "🎵" },
  { "id": 9, "name": "PE", "color": "#64748b", "emoji": "⚽" }
]

GET /api/assignments/today

Get today's assignments based on current date.

Request

GET /api/assignments/today

Response

Same format as week assignments, filtered to current day.

Logic

// Calculates current week and day based on:
// - School year start date
// - Current date
// - Day of week (1=Mon, 5=Fri)

Curriculum Audit & Repair

GET /api/curriculum/audit

Scans all active (non-graded, non-cancelled) assignments for a student and flags alignment issues.

Query parameters:

  • student_id - UUID (defaults to Lucas)

Response:

{
  "total_issues": 23,
  "total_assignments_scanned": 588,
  "issues": {
    "weekend_dates": [{ "student_assignment_id", "title", "current_due_date", "suggested_due_date", ... }],
    "out_of_range": [{ "student_assignment_id", "title", "due_date", "assigned_week", "actual_week_number", ... }],
    "null_due_dates": [{ "student_assignment_id", "title", "week_number", ... }],
    "sequence_breaks": [{ "resource", "earlier_title", "later_title", ... }]
  },
  "school_weeks": [{ "id", "week_number", "start_date", "end_date" }]
}

POST /api/curriculum/repair

Applies date fixes to misaligned assignments. Updates due_date, week_id, and day_of_week in a single transaction.

Request body:

{
  "fixes": [
    { "student_assignment_id": "uuid", "new_due_date": "2026-02-11" }
  ]
}

Validation: Rejects weekend dates and dates outside school weeks. Rolls back all changes if entire batch fails.

Response:

{
  "message": "Successfully repaired 5 assignments",
  "repaired": 5,
  "failed": 0,
  "results": [{ "student_assignment_id", "new_due_date", "new_week_number", "new_day_of_week" }]
}

Vocabulary Review

GET /api/vocab-review/:assignmentId

Returns vocabulary terms for a review assignment. Resolves the unit key from the assignment's title/resource and fetches from vocab_sets table.

Query parameters:

  • student_id - UUID (optional, includes student assignment status)

Response:

{
  "assignment": { "id", "title", "subject", "resource" },
  "unit_key": "ckhg-unit-1",
  "terms": [
    { "id", "term": "river", "definition": "A large natural stream...", "example_sentence": "The Nile is...", "display_order": 1 }
  ],
  "student_assignment": { "id", "status", "due_date" }
}

POST /api/vocab-review/:assignmentId/complete

Auto-grades the vocabulary review and creates a submission. Calculates grade from fill-in-the-blank score.

Request body:

{
  "student_id": "uuid",
  "student_assignment_id": "uuid",
  "score": 18,
  "total": 18,
  "attempts": 1,
  "results": [{ "term": "river", "answer": "river", "correct": true }]
}

Response:

{
  "message": "Vocabulary review completed and graded",
  "grade": "A",
  "score": 18,
  "total": 18,
  "feedback": "Vocabulary Review completed. 18/18 correct (100%). Perfect on first try!"
}

Error Handling

All endpoints return consistent error responses:

{
  "error": "Error message here",
  "status": 404,
  "timestamp": "2025-11-28T10:30:00.000Z"
}

Status Codes

200Success
400Bad request (invalid parameters)
404Resource not found
500Server error (database issue)

Frontend Usage

// Fetch weeks
const response = await fetch('http://localhost:3000/api/weeks');
const weeks = await response.json();

// Fetch assignments for week 1
const response = await fetch('http://localhost:3000/api/weeks/1/assignments');
const assignments = await response.json();

// Fetch with day filter
const monday = await fetch('http://localhost:3000/api/weeks/1/assignments?day=1');
const mondayWork = await monday.json();

Database Connection

// .env.local configuration
DATABASE_URL=postgresql://postgres:password@localhost:5432/andrews_family_lms

// Or individual settings
DB_HOST=localhost
DB_PORT=5432
DB_NAME=andrews_family_lms
DB_USER=postgres
DB_PASSWORD=your_password