1. Front Matter
Title: Enrollment
Author: Joshua Uriel Tribiana
Reviewers: Joylynne Esportuno ( teruterubozuuu )
Creation Date: 2026-06-29
Status: Approved
References:
Issue: [6.2] Enrollment
2. Introduction & Goals
Problem Summary
Creators need a quick and efficient system to manage learner access to their quests. The Enrollment feature provides the necessary tools for creators to add learners individually or in bulk via CSV upload, track their status, and manage their access. This is a core function for distributing content within the WyzQuests platform.Goals
Provide a UI for creators to enroll a single learner by name and email.
Provide a UI for creators to bulk-enroll learners by uploading a CSV file.
Send an email notification to newly enrolled learners.
Persist enrollment records, linking learners to quests.
Allow creators to view all enrolled learners for a quest.
Allow creators to update an enrollee's status (
ongoingvs.finished).Allow creators to delete an enrollment (revoke access).
Non-Goals
Self-enrollment via a public link.
Payment processing or paid course enrollment.
Automatic enrollment based on learner groups (this is a separate feature, [11.5]).
Detailed error reporting for individual failed rows in a CSV upload (noted as a scope gap).
Glossary
Enrollment: A record in the
quest_enrollmentstable that links a learner (learner_id) to a specific quest (quest_id).Enrollee: A learner who has been enrolled in a quest.
3. High-Level Architecture
System Diagram
Learner Enrollment WorkflowCreator Actions───────────────+----------------------+| Add Learner || (Manual Entry) |+----------------------+||| +----------------------+| | Upload CSV File || +----------------------+| || v| +----------------------+| | Parse CSV || +----------------------+| |+---------------+----------------+|v+----------------------+| Enrollment API |+----------------------+|v+----------------------+| Save Enrollment || to Database |+----------------------+|v+----------------------+| Send Enrollment || Email |+----------------------+Enrollment Management─────────────────────+----------------------+| Open Enrollee List |+----------------------+|v+----------------------+| Retrieve || Enrollments |+----------------------+|v+----------------------+| Display Enrollees || in Table |+----------------------+Technologies Used
Next.js: For API routes and frontend components.
React: For UI components like
AddLearnerModalandEnrolleeTable.Supabase (PostgreSQL): For storing
quest_enrollmentsdata.Clerk: For authenticating the creator performing the enrollment.
Zod: For validating request bodies.
Papaparse: For client-side parsing of CSV files for bulk enrollment.
Nodemailer: For sending enrollment notification emails.
4. Detailed Design & Implementation
Data Model / Schema
The feature primarily interacts with thequest_enrollmentstable.quest_enrollmentsTable:Column
Type
Description
idUUIDPrimary Key.
quest_idUUIDForeign key to the
queststable.learner_idTEXTThe Clerk ID of the enrolled learner.
statusTEXTEnrollment status (
ongoingorfinished).progressJSONBStores learner's progress data.
created_atTIMESTAMPTZTimestamp of when the enrollment was created.
updated_atTIMESTAMPTZTimestamp of the last update.
API Specification
POST /api/creator/enrollment/create-enrollmentAuth: Creator must own the quest.
Body:
{ quest_id: string, learner_name: string, learner_email: string }Action: Creates a single enrollment record. If the user doesn't exist, an
app_usersrecord is created first. Triggers an email notification.
POST /api/creator/enrollment/bulk-createAuth: Creator must own the quest.
Body:
{ quest_id: string, learners: { name: string, email: string }[] }Action: Creates multiple enrollment records in a transaction. Triggers email notifications for each new enrollee.
GET /api/creator/enrollment/list?quest_id=<uuid>Auth: Creator must own the quest.
Action: Returns a list of all enrollees for the specified quest.
PATCH /api/creator/enrollment/update-statusAuth: Creator must own the quest.
Body:
{ enrollment_id: string, status: "ongoing" | "finished" }Action: Updates the status of a single enrollment.
DELETE /api/creator/enrollment/deleteAuth: Creator must own the quest.
Body:
{ enrollment_id: string }Action: Permanently deletes an enrollment record.
Logic & Workflows
Single Enrollment:
The creator fills out the
AddLearnerModal.Client-side validation checks for a valid name and email format.
On submit, the
EnrollmentServicecalls thecreate-enrollmentAPI.The API creates the enrollment, and the backend sends a notification email.
The UI optimistically updates the
EnrolleeTablewith the new learner.
Bulk Enrollment (CSV):
The creator selects a CSV file with
nameandemailcolumns.papaparseparses the file on the client into an array of learner objects.The
EnrollmentServicecalls thebulk-createAPI with the array of learners.The backend processes the learners in a batch, creating enrollments and sending emails.
The UI refetches the enrollment list to display the newly added learners.
Key Files:
app/quest-editor/[questID]/(sections)/enrollment/page.tsx: The main page that orchestrates the components.lib/enrollment/enrollmentService.ts: The service layer abstracting all API calls.components/creator/enrollment/AddLearnerModal.tsx: The modal for adding a single learner.components/creator/enrollment/EnrolleeTable.tsx: The table for displaying and managing enrollees.app/api/creator/enrollment/create-enrollment/route.ts: API for single enrollment.app/api/creator/enrollment/bulk-create/route.ts: API for bulk enrollment.
5. Infrastructure & Operations
Dependencies
Internal: Relies on the
questsandapp_userstables.External:
Supabase (PostgreSQL) for data storage.
An SMTP provider configured for Nodemailer to send emails.
Monitoring & Alerting
Standard monitoring for all
/api/creator/enrollment/*endpoints.Alerts should be configured for a high rate of
5xxerrors, which could indicate a database or email service issue.Log email sending failures with high severity.
Deployment Plan
Database Migrations: The
quest_enrollmentstable and related RLS policies must be deployed.Environment Variables: Ensure
SMTP_HOST,SMTP_USER,SMTP_PASS, etc., are configured for the email service.Rollout: The feature can be deployed directly as it is a core part of the quest editor workflow.
6. Testing & Quality Assurance
Test Strategy
As per the ENROLLMENT_REFACTORING.md documentation, this feature has comprehensive test coverage.
Unit Tests (
enrollmentService.test.ts):Mock
fetchto test all methods in theEnrollmentService.Verify correct API endpoints, methods, and body payloads are used.
Test both success and error responses from the mocked API.
Component Tests (
AddLearnerModal.test.tsx):Test rendering and visibility.
Test input validation for name (required) and email (required, format).
Test form submission, loading states, and error display.
End-to-End (E2E) / QA:
Flow 1 (Single Add): Add a new learner -> Verify they appear in the table -> Verify they receive an enrollment email.
Flow 2 (Bulk Add): Upload a valid CSV -> Verify all learners appear in the table.
Flow 3 (Manage): Change a learner's status -> Verify it updates. Delete a learner -> Verify they are removed.
Negative Test: Upload a malformed CSV; verify an error is shown.
Known Limitations
CSV Error Reporting: The current implementation has a basic "happy path" for CSV uploads. It does not provide detailed feedback on which specific rows failed during a bulk import. This is a known scope gap for future improvement.
7. Maintenance & Support
Troubleshooting
Learner not appearing in the table after being added:
This is likely a client-side state issue or a failed API call.
Check the browser's developer console for network errors on the
create-enrollmentorlistAPI calls.Ask the user to refresh the page to force a refetch from the database.
Enrollment emails are not being sent:
Check the server logs for errors from Nodemailer or the SMTP provider.
Verify that SMTP environment variables are correctly configured in the deployment environment.
Bulk CSV upload fails:
Ensure the CSV has
nameandemailheaders.Check for formatting issues in the CSV file (e.g., incorrect delimiters).
Changelog
1.0 - Approved, Feature refactored and documented, 2026-06-29