Student Management

The student management page is the primary view for tracking every child on the platform, from initial intake through active tutoring. Coordinators use it to monitor funnel health, assign tutors, and ensure no student falls through the cracks.

Student List

The student list at /admin/students is a paginated, filterable table showing all children on the platform. It supports funnel-based filtering to help coordinators focus on specific stages.

GET /admin/students
// Query parameters
?page=1&limit=25&funnel=active&search=ethan

// Response
{ "students": [...], "total": 142, "page": 1, "limit": 25 }

Funnel Tabs

The student list has tabbed filters that segment the funnel. Badge counts are loaded separately for performance.

Active Children with at least one active tutor match and recent sessions. Filter: funnel=active
Awaiting Children with a posting but no accepted match yet. Filter: funnel=awaiting
Has Options Children with tutor applications pushed to parent but not yet accepted. Filter: funnel=has_options
Needs Attention Children with issues: no posting, stale match, missing intake, or inactive. Filter: funnel=needs_attention
GET /admin/students/counts
// Returns badge numbers for each funnel tab
{ "active": 42, "awaiting": 8, "has_options": 5, "needs_attention": 3 }

Student Detail Page

Clicking a student opens the detail view at /admin/students/view/[id]/ with four sub-routes accessible via tabs.

Sub-routeContent
/overviewChild profile (name, age, school, special needs), parent contact info, current status, intake summary
/tutorsActive tutor matches with match date, subject, session count. Tutor names shown only after Parent_Accepted
/sessionsFull session history with status badges, check-in/out times, and tutor notes preview
/insightsTutor observations, AI-generated snapshots, parent reviews, and readiness reports

Name Display Convention

ID-tagged names

All admin pages display names in the format {display_name} ({id}) -- for example, "Amelia (2)" or "Alex Tan (9)". This ensures coordinators can always disambiguate people with similar names.

Supporting Endpoints

Recent Sessions

GET /admin/students/:id/recent-sessions
// Returns the last N sessions for a specific student
[{ "id": 301, "date": "2026-03-20", "status": "Approved",
   "tutor_name": "Alex Tan (9)", "subject": "Math",
   "checked_in_at": "...", "checked_out_at": "..." }]

Pool Status

GET /admin/students/:id/pool-status
// Shows which tutor pool the student is in and match candidates
{ "child_id": 12, "pool": "matching",
  "candidates": [{ "tutor_id": 9, "score": 78, "status": "Pushed" }] }

Parent Detail

GET /admin/parents/:id/detail
// Full parent profile with all children and package info
{ "parent_id": 5, "name": "Sarah Lim", "email": "...",
  "phone": "...", "children": [...], "packages": [...] }

Parent Account Maintenance

PATCH /admin/parents/:id/account
// Coordinator-only account maintenance for linked parent users
{ "email": "[email protected]", "password": "demo" }

// Response
{ "parent_user_id": 1789, "updated_fields": ["email", "password"], "password_updated": true,
  "parent": { "id": 1789, "email": "[email protected]", "display_name": "...", "phone": "..." } }

This route is intended for coordinator/operator fixes through the existing worker, not for parent self-service. It supports temporary-password resets for account recovery and email correction after resolving the linked family from the student detail.

Child Insights

The insights system aggregates tutor observations and AI-generated summaries for each child over time.

EndpointDescription
GET /insights/admin/childrenList all children with insight summaries (paginated)
GET /insights/admin/children/:idFull insight detail for a specific child: observations, snapshots, trend analysis

Readiness Reports

Tutoring Readiness profiles are parent-filled questionnaires scoring children across developmental and learning domains. Alerts trigger when a child has a match (even before first session). Multiple snapshots over time track progress.

GET /admin/readiness
// Returns all readiness reports across all children
[{ "child_id": 12, "child_name": "Ethan", "status": "Completed",
   "total_b": 8, "total_c": 10, "total_d": 9, "total_e": 7, "total_g": 18, "total_h": 6, "overall_af": 40 }]

Readiness Domains

DomainNameWhat it measures
BEmotional RegulationManaging frustration, recovery, calming strategies. Includes coping_mechanisms text field.
CCommunication & SocialExpressing needs, turn-taking, peer interaction
DLearning ReadinessFocus, curiosity, willingness to attempt new tasks
EIndependence & Self-ManagementWorking without prompting, organizing materials, time awareness
GLiteracy & NumeracyAge-appropriate reading, writing, and math foundations (9 items)
HSensory ProcessingSensory sensitivity, sensory seeking, sensory avoidance, self-regulation strategies
Removed Domains

Domains A (Classroom Compliance) and F (Group Readiness) were removed as they are not relevant for 1:1 tutoring. Legacy reports with A/F scores are preserved for backward compatibility.

Each item is scored 0-3: 0 = Not Yet, 1 = With Full Support, 2 = With Some Support, 3 = Independently. Each domain also has a free-text notes field for qualitative observations. Overall score = B+C+D+E+H (G scored separately).

Subject-Specific Proficiency

In addition to developmental domains, the readiness report includes subject-specific proficiency questions based on the child's level and subject. 459 curriculum topics across 3 subjects are stored in proficiency-topics.json:

SubjectLevelsTopics
English21 (Primary 1-6 Standard/Foundation, Secondary 1-5 G1/G2/G3)117
Maths21 (Primary 1-6 Standard/Foundation, Secondary 1-5 G1/G2/G3)222
Science19 (Primary 3-6 Standard/Foundation, Secondary 1-5 G1/G2/G3)120

Each topic uses a 4-point scale: Not Yet Started, Beginning, Getting There, Proficient. Scores are stored in proficiency_scores_json on the readiness report.

Soft Delete

Child deactivation

When a parent removes a child, the record is not deleted. Instead, a deactivated_at timestamp is set. The parent list filters out deactivated children, but admin views show all children including deactivated ones (greyed out).

DELETE /children/:id
// Sets deactivated_at = NOW() -- does not delete the record
// Response: 200 OK
{ "success": true, "deactivated_at": "2026-03-27T10:30:00Z" }