Admin Spec — Semester Management
Semester Management
Domain 3 of the Enhanced Candidate A navigation structure. Contains: Semesters list + Semester Hub Page (4 tabs: Overview, Setup Checklist, Enrollment, Close Workflow), Welcome Package, Email Management, Tags, Operations. Primary workflows served: WF1 (Semester Setup), WF3 (Semester Close)
1. Domain Overview
Semester Management groups everything related to the lifecycle of a semester -- from initial setup through active management to close. Moving Welcome Package, Email Management, Tags, and Operations here from the former Settings section puts them where they logically belong: these are all semester-scoped configuration items.
Key design decisions:
- Semester Hub Page is the centerpiece -- a multi-tab entity page consolidating all semester configuration, enrollment visibility, and close workflow into one place
- Setup Checklist is a borrowed workflow concept (from WS1.3) that tracks completion without enforcing sequence -- the admin can configure items in any order
- Close Workflow is a borrowed workflow concept with GATED steps -- payment setup cannot proceed until promotions are finalized (directly addresses WS2 billing pain point)
- Tags moved here because tags are created per semester (semester-scoped)
- Operations moved here because bulk actions (promotions, registrations) are semester events; absorbs Level 0 promotion from dissolved Students Management grab-bag
Sidebar items:
Semester Management
Semesters <- from top-level
[Semester Hub Page] (NEW -- rich multi-tab semester view)
[Tab: Overview]
[Tab: Setup Checklist] (NEW)
[Tab: Enrollment] (NEW)
[Tab: Close Workflow] (NEW)
Welcome Package <- from Settings
Email Management <- from Settings
Tags <- from Settings
Operations (bulk actions) <- from Settings (absorbs Level 0 promotion)
Data tables referenced: semester, user_link_level_tag, lessonsnew, assessment, resources, live_sessions, recordings, tutorials, mcqquestion, quiz, level_tag, users, user_profile, emails, tags, subscriptions, group_members, group_name
Workarounds Eliminated
| ID | Workaround | Current Tool | Replaced By |
|---|---|---|---|
| W1 | Semester setup tracked via personal checklists | Google Sheets / paper | Setup Checklist tab (Section 3.6) |
| W2 | Content readiness verified by visiting each screen individually | Manual navigation (19+ screens) | Setup Checklist with inline previews and deep links (Section 3.6) |
| W3 | Promotion decisions tracked in spreadsheet before billing | Google Sheets | Close Workflow Steps 1-2 with gating (Section 3.8) |
| W4 | Payment setup done before promotions finalized | Stripe Dashboard + guesswork | Close Workflow gate between Step 2 and Step 3 (Section 3.8) |
| W5 | Semester close tasks tracked manually with no verification | Email / verbal confirmation | Close Workflow Step 5 verification dashboard (Section 3.8) |
| W6 | Enrollment counts require manual cross-referencing | Database queries | Enrollment tab with live counts and filters (Section 3.7) |
2. Screen: Semesters List
2.1 Purpose
View all semesters with their status. Entry point to Semester Hub pages.
2.2 Entry Points
- Sidebar: Semester Management > Semesters
- Dashboard: phase prompt click
2.3 Layout
Data table (small dataset, no pagination needed). Uses standard Data Table pattern from 01-global-patterns.md Section 4.1. No filter bar (typically <10 semesters).
2.4 Data Displayed
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Name | semester.name |
Yes (default: most recent first by start_date) |
Clickable --> Semester Hub |
| Start Date | semester.start_date |
Yes | Formatted as "Mar 10, 2026" |
| End Date | semester.end_date |
Yes | Formatted as "Jul 15, 2026" |
| Registration | semester.registration_status |
Yes | Badge: Open (green, when registration_status = 1) / Closed (gray, when registration_status = 0) |
| Status | semester.is_current |
Yes | Badge: Active (green, when is_current = 1) / Inactive (gray, when is_current = 0 and dates are past) / Draft (blue, when is_current = 0 and start_date is in the future) |
| Students | Count of user_link_level_tag where semester_id = this semester |
Yes | Number (e.g., "247") |
| Setup Progress (NEW) | Computed: checklist completion percentage (configured items / total applicable items from Setup Checklist) | No | Progress bar or "X/Y" format (e.g., "14/18 configured") |
2.5 Actions
| Action | Trigger | Permission | Behavior | Confirmation |
|---|---|---|---|---|
| View Semester | Row click | All | Navigates to Semester Hub Page (default tab: Overview) | No |
| Create Semester | "Create Semester" button (top-right) | Admin | Opens create modal: Name (text), Start Date (date picker), End Date (date picker), Registration Start Date (date picker, optional), Content Availability Date (date picker, optional). On save: creates semester record with is_current = 0 and registration_status = 0, auto-creates default Setup Checklist items. Toast: "Semester '[name]' created." |
No |
| Delete Semester | Delete icon on row (rightmost column) | Admin | Blocked if students enrolled: button disabled with tooltip "Cannot delete: X students enrolled. Remove all enrollments first." If 0 students: destructive confirmation (01-global-patterns.md Section 4.6): "Delete [name]? All associated content, email templates, and tags will be permanently removed. This cannot be undone." On confirm: deletes semester record and cascades to associated content records. |
Destructive |
2.6 States
| State | Display |
|---|---|
| Has semesters | Data table with semester rows, sorted by start date descending |
| No semesters | Empty state (01-global-patterns.md Section 4.8): "No semesters created." + "Create Semester" button |
| Loading | Skeleton data table (01-global-patterns.md Section 4.9) |
| Error | "Unable to load semesters. Please try again." + "Retry" button |
2.7 Role Visibility
- Admin: Full view + Create/Delete actions
- View-Only: View table only (no Create or Delete buttons)
- TA / Support Staff: Hidden (sidebar item not visible, per 01-global-patterns.md Section 3.2)
3. Screen: Semester Hub Page (Rich Entity Page)
3.1 Purpose
Single consolidated view of everything about a semester: configuration, content setup status, enrolled students, and close workflow. This is the second most complex entity page in the system (after Student Detail Page with 6 tabs). Directly addresses WF1 (19+ screens --> 8-10) and WF3 (8+ screens --> 4-6).
3.2 Entry Points
- Semesters list: row click
- Dashboard: phase prompt link (e.g., "Spring 2026 -- Setup Phase" click)
- Global search: semester result click (01-global-patterns.md Section 2.3)
- Student Detail > Semester History tab: semester name click (03-student-management.md)
- Setup Checklist deep link return ("Return to Checklist" affordance from content screens -- see Section 3.6)
3.3 Entity Header
Persistent header visible across all tabs (follows Entity Page pattern from 01-global-patterns.md Section 4.11):
| Field | Source | Format |
|---|---|---|
| Semester Name | semester.name |
Large text (page title) |
| Date Range | semester.start_date -- semester.end_date |
Text: "Mar 10 -- Jul 15, 2026" |
| Status | semester.is_current |
Badge: Active (green, is_current = 1) / Inactive (gray, is_current = 0 and dates past) / Draft (blue, is_current = 0 and start_date future) |
| Registration | semester.registration_status |
Badge: Open (green, registration_status = 1) / Closed (gray, registration_status = 0) |
| Phase (NEW) | Computed from dates and status: if start_date > today then "Setup"; if is_current = 1 and today between start_date and end_date then "Active"; if today > end_date or close workflow started then "Close" |
Phase badge: Setup (blue) / Active (green) / Close (amber) |
| Students Enrolled | Count of user_link_level_tag where semester_id = this semester and user_semester_status = 1 (enrolled) |
Number (e.g., "247 students") |
| Setup Progress (NEW) | Checklist completion percentage (from Setup Checklist tab data) | "X of Y configured" + progress bar |
Breadcrumb: Semester Management > Semesters > [Semester Name]
3.4 Tab Structure
| Tab | Label | Badge | Default |
|---|---|---|---|
| 1 | Overview | -- | Yes |
| 2 | Setup Checklist | "X remaining" count (number of unconfigured, non-N/A items) | No |
| 3 | Enrollment | Student count (total enrolled) | No |
| 4 | Close Workflow | Step indicator "Step X of 5" (current step number) | No |
Tab behavior follows 01-global-patterns.md Section 4.11: lazy-load on first activation, state preserved when switching, URL updates with tab name (e.g., /semesters/123#setup-checklist), sticky tab bar on scroll.
3.5 Tab: Overview
Data Displayed
Dates section (card layout with inline documentation -- info icon tooltips on each field, per 01-global-patterns.md Section 6.1):
| Field | Source | Display | Tooltip |
|---|---|---|---|
| Start Date | semester.start_date |
Formatted date or "Not set" with "Set Date" link | "The first day of the semester. Students can begin lessons on this date." |
| End Date | semester.end_date |
Formatted date or "Not set" with "Set Date" link | "The last day of the semester. Determines when close workflow should begin." |
| Registration Start | semester.registration_start_date |
Formatted date or "Not set" with "Set Date" link | "When the registration form opens. Can be before the semester start date." |
| Content Availability Date | semester.content_availability_date |
Formatted date or "Not set" with "Set Date" link | "When students can see this semester's content in the app. Can differ from start date." |
Status Controls section (toggle switches with inline documentation):
| Control | Source | Behavior | Tooltip |
|---|---|---|---|
| Registration Open | semester.registration_status toggle (maps to 1/0) |
Toggles registration open/closed. Updates registration_status in database. Toast: "Registration [opened/closed] for [semester name]." |
"When ON, students can register for this semester. Turn OFF after enrollment is complete." |
| Active Semester | semester.is_current toggle (maps to 1/0) |
Makes this the active semester. WARNING modal before toggle: "Setting this as active will deactivate any currently active semester. Content will be served from this semester. Continue?" On confirm: sets is_current = 1 for this semester, sets is_current = 0 for all other semesters. Toast: "[Semester name] is now the active semester." |
"Only one semester can be active at a time. The active semester's content is served to students in the app." |
| Auto-Transition (NEW) | New field: semester.auto_transition_enabled + uses existing date fields |
Toggle + date preview. When enabled, shows: "Will activate on [start_date] and deactivate on [end_date]." When toggled ON: confirmation "Enable auto-transition? This semester will automatically become active on [start_date] and deactivate on [end_date]." | "When enabled, this semester will automatically become active on its start date and deactivate on its end date. Requires both start and end dates to be set." |
Automation section (NEW -- read-only summary cards):
| Field | Source | Purpose |
|---|---|---|
| Email Schedule Preview | Query emails table where semester_id = this semester, ordered by trigger date |
Shows list of configured automated emails with their trigger conditions and scheduled dates. Format: "[Template Name] -- [Trigger] -- [Date or 'On event']". Example: "Welcome Email -- On registration -- Immediate", "Week 1 Reminder -- Week 1 start -- Mar 17, 2026" |
| Upcoming Automations | Computed from dates and settings | List of scheduled automated actions with countdown. Examples: "Registration closes in 3 days (Mar 13)", "Semester activates in 7 days (Mar 17)", "Content becomes available in 5 days (Mar 15)", "Auto-transition scheduled: Mar 17" |
Actions
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Edit Dates | "Edit" button on Dates section header | Admin | Inline edit mode: date fields become date pickers. "Save" / "Cancel" buttons appear. On save: updates semester record. Toast: "Dates updated." |
| Toggle Controls | Toggle switches in Status Controls section | Admin | See individual toggle behaviors above |
| Preview Email Schedule | "View All Emails" link in Automation section | All | Navigates to Semester Management > Email Management filtered to this semester |
States
| State | Display |
|---|---|
| Fully configured | All dates set, status controls shown with current values, automation section populated |
| New semester | Some dates may be "Not set" -- each empty field shows "Not set" with "Set Date" link (clicking enters inline edit mode for that field). Automation section shows "No automations scheduled -- configure dates and email templates to see scheduled actions." |
| Loading | Skeleton cards for each section (01-global-patterns.md Section 4.9) |
| Error | "Unable to load semester details. Please try again." + "Retry" button |
3.6 Tab: Setup Checklist (NEW)
Borrowed from Workflow framework (WS1.3): tracks completion without enforcing sequence. The admin can configure items in any order. Enhanced with Candidate C elements: deep links to content screens with semester pre-filtered, inline content previews, and "return to checklist" affordance.
Layout
Grouped checklist with overall progress bar at top. Each group is a collapsible section. Each item shows status, count, and action link.
Overall Progress
Top of tab: progress summary card.
| Element | Source | Format |
|---|---|---|
| Progress Text | Computed: configured items / total applicable items (excluding N/A) | "Setup Progress: X of Y items configured (Z%)" |
| Progress Bar | Same computation | Visual progress bar: green fill proportional to completion percentage |
| Status Message | Computed from percentage | At 100%: green message "All setup items configured for [Semester Name]." At <100%: amber message "X items remaining." |
Checklist Structure
Items grouped by content type. Within each group, one item per level (where applicable) or one aggregate item (where content is not level-scoped).
Group: Video Lessons
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X videos" / Not Configured: amber circle + "Not Configured" | "Configure -->" deep link to Content > Video Lessons with URL params ?semester=[id]&level=0 (semester + Level 0 pre-filtered) |
| Level 1 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Level 1 tag ID |
Same pattern | Deep link to Content > Video Lessons with ?semester=[id]&level=1 |
| Level 2 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Level 2 tag ID |
Same pattern | Deep link with ?semester=[id]&level=2 |
| Level 3 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Level 3 tag ID |
Same pattern | Deep link with ?semester=[id]&level=3 |
| Level 4 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Level 4 tag ID |
Same pattern | Deep link with ?semester=[id]&level=4 |
| Year 2 Video Lessons | Count of lessonsnew where semester_id = this semester AND level_tag_id = Year 2 tag ID |
Same pattern | Deep link with ?semester=[id]&level=year2 |
Group: Assessments (Submissions)
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 Assessments | Count of assessment where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X prompts" / Not Configured: amber circle | "Configure -->" deep link to Student Management > Submissions with ?semester=[id]&level=0 |
| Level 1 Assessments | Same query pattern for Level 1 | Same display pattern | Deep link with ?semester=[id]&level=1 |
| Level 2 Assessments | Same query pattern for Level 2 | Same display pattern | Deep link with ?semester=[id]&level=2 |
| Level 3 Assessments | Same query pattern for Level 3 | Same display pattern | Deep link with ?semester=[id]&level=3 |
| Level 4 Assessments | Same query pattern for Level 4 | Same display pattern | Deep link with ?semester=[id]&level=4 |
| Year 2 Assessments | Same query pattern for Year 2 | Same display pattern | Deep link with ?semester=[id]&level=year2 |
Group: Resources
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 Resources | Count of resources where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X files" / Not Configured: amber circle | "Configure -->" deep link to Content > Resources with ?semester=[id]&level=0 |
| Level 1 Resources | Same pattern for Level 1 | Same | Deep link with ?semester=[id]&level=1 |
| Level 2 Resources | Same pattern for Level 2 | Same | Deep link with ?semester=[id]&level=2 |
| Level 3 Resources | Same pattern for Level 3 | Same | Deep link with ?semester=[id]&level=3 |
| Level 4 Resources | Same pattern for Level 4 | Same | Deep link with ?semester=[id]&level=4 |
| Year 2 Resources | Same pattern for Year 2 | Same | Deep link with ?semester=[id]&level=year2 |
Group: Live Sessions
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Live Sessions (all levels) | Count of live_sessions where semester_id = this semester |
Configured: green checkmark + "X sessions" / Not Configured: amber circle | "Configure -->" deep link to Scheduling > Live Sessions with ?semester=[id] |
Group: Recordings
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Recordings (all levels) | Count of recordings where semester_id = this semester |
Configured: green checkmark + "X recordings" / Not Configured: amber circle | "Configure -->" deep link to Content > Recordings with ?semester=[id] |
Group: Tutorials
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 Tutorials | Count of tutorials where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X tutorials" / Not Configured: amber circle | "Configure -->" deep link to Content > Tutorials with ?semester=[id]&level=0 |
| Level 1 Tutorials | Same pattern | Same | Deep link with ?semester=[id]&level=1 |
| Level 2 Tutorials | Same pattern | Same | Deep link with ?semester=[id]&level=2 |
| Level 3 Tutorials | Same pattern | Same | Deep link with ?semester=[id]&level=3 |
| Level 4 Tutorials | Same pattern | Same | Deep link with ?semester=[id]&level=4 |
| Year 2 Tutorials | Same pattern | Same | Deep link with ?semester=[id]&level=year2 |
Group: Quizzes
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 Quizzes | Count of quiz where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X quizzes" / Not Configured: amber circle | "Configure -->" deep link to Content > Quizzes with ?semester=[id]&level=0 |
| Level 1 Quizzes | Same pattern | Same | Deep link with ?semester=[id]&level=1 |
| Level 2 Quizzes | Same pattern | Same | Deep link with ?semester=[id]&level=2 |
| Level 3 Quizzes | Same pattern | Same | Deep link with ?semester=[id]&level=3 |
| Level 4 Quizzes | Same pattern | Same | Deep link with ?semester=[id]&level=4 |
| Year 2 Quizzes | Same pattern | Same | Deep link with ?semester=[id]&level=year2 |
Group: MCQ Questions
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Level 0 MCQ Questions | Count of mcqquestion where semester_id = this semester AND level_tag_id = Level 0 tag ID |
Configured: green checkmark + "X questions" / Not Configured: amber circle | "Configure -->" deep link to Content > MCQ Questions with ?semester=[id]&level=0 |
| Level 1 MCQ Questions | Same pattern | Same | Deep link with ?semester=[id]&level=1 |
| Level 2 MCQ Questions | Same pattern | Same | Deep link with ?semester=[id]&level=2 |
| Level 3 MCQ Questions | Same pattern | Same | Deep link with ?semester=[id]&level=3 |
| Level 4 MCQ Questions | Same pattern | Same | Deep link with ?semester=[id]&level=4 |
| Year 2 MCQ Questions | Same pattern | Same | Deep link with ?semester=[id]&level=year2 |
Group: Configuration
| Item | Status Source | Status Display | Action |
|---|---|---|---|
| Welcome Package | Count of welcome package resources for this semester | Configured: green checkmark + "X files" / Not Configured: amber circle | "Configure -->" deep link to Semester Management > Welcome Package with ?semester=[id] |
| Email Templates | Count of emails where semester_id = this semester |
Configured: green checkmark + "X templates" / Not Configured: amber circle | "Configure -->" deep link to Semester Management > Email Management with ?semester=[id] |
| Tags | Count of tags where semester_id = this semester |
Configured: green checkmark + "X tags" / Not Configured: amber circle | "Configure -->" deep link to Semester Management > Tags with ?semester=[id] |
| Teacher Assignments | Whether TAs have been assigned to groups for this semester (check group_name records where semester_id = this semester that have associated group_members) |
Configured: green checkmark + "X groups assigned" / Not Configured: amber circle | "Configure -->" deep link to Teacher Management > Teacher Assignment Criteria |
| TA Schedules | Whether TA availability slots exist for this semester's date range (check TA schedule records overlapping start_date to end_date) |
Configured: green checkmark / Not Configured: amber circle | "Configure -->" deep link to Scheduling > TA Schedules |
| Holidays | Whether holiday records exist for this semester's date range | Configured: green checkmark + "X holidays" / Not Configured: amber circle | "Configure -->" deep link to Scheduling > Holidays |
Inline Content Preview (from Candidate C)
Each item with "Configured" status includes an expandable preview:
- Collapsed (default): Shows status badge + count only (e.g., "12 videos")
- Expanded (click to expand): Shows the first 3 items inline without navigating away:
- Video Lessons: thumbnail + title for the first 3 videos
- Resources: file icon + title for the first 3 resources
- Assessments: prompt title for the first 3 assessment prompts
- Email Templates: template name + trigger for the first 3 templates
- Other content types: title/name for the first 3 items
- "View all X items -->" link at bottom of expanded preview: navigates to the full content screen with semester pre-filtered (same as "Configure -->" link)
"Return to Checklist" Affordance (from Candidate C)
When navigating from a checklist deep link to a content screen:
| Element | Behavior |
|---|---|
| Banner | A persistent banner appears at the top of the target content screen: "<-- Return to Setup Checklist for [Semester Name]" |
| Trigger | Presence of query parameters ?from=checklist&semester=[id] in the URL |
| Click behavior | Returns to the Semester Hub > Setup Checklist tab with scroll position preserved (scroll position stored in session state before navigation) |
| Dismissal | Banner disappears if the admin navigates away from the content screen via sidebar or breadcrumb (i.e., not via the "Return" link) |
Actions
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Mark as N/A | Checkbox per item (appears on hover or always visible) | Admin | Toggles item as "Not Applicable" -- grays out the item, excludes it from progress count. Toast: "[Item] marked as N/A." Reversible: uncheck to restore. |
| Add Note | Note icon per item (appears on hover) | Admin | Opens inline text input below the item. Free text note for tracking (e.g., "Waiting on Vimeo upload from instructor"). Note appears as small gray text below the item when saved. Editable and deletable. |
| Clone from Previous (NEW) | "Clone from [Previous Semester]" button per group header | Admin | Dropdown showing previous semesters. On select: confirmation "Clone all [content type] from [Previous Semester] to [Current Semester]? This creates independent copies (not linked to the original)." On confirm: copies all content records of that type from the selected semester, creating new records with this semester's ID. Progress updates after clone. Toast: "Cloned X [content type] from [Previous Semester]." Assumption (OQ5): Independent copies, not linked -- per 00-spec-index.md. |
| Clone All Content | "Clone All from Previous Semester" button at top of tab (prominent when nothing configured) | Admin | Same as per-group clone but applies to ALL content groups. Confirmation: "Clone ALL content from [Previous Semester] to [Current Semester]? This will copy video lessons, assessments, resources, tutorials, quizzes, MCQ questions, email templates, tags, and welcome package files. Existing content in [Current Semester] will NOT be overwritten." |
| Navigate to Configure | "Configure -->" link per item | Admin | Deep links to the target content screen with semester (and level, where applicable) pre-filtered via URL parameters. Sets ?from=checklist&semester=[id] to enable the "Return to Checklist" banner. |
States
| State | Display |
|---|---|
| All configured | Progress bar at 100%. Green message: "All setup items configured for [Semester Name]." All items show green checkmarks. |
| Partially configured | Progress bar shows percentage. Unconfigured items shown with amber circle and "Not Configured" text. Unconfigured items have subtle amber left border for visibility. |
| Nothing configured | Progress bar at 0%. Message: "No content has been configured for this semester." "Clone All from Previous Semester" button displayed prominently. |
| Loading | Skeleton checklist with placeholder groups and items |
| Error | "Unable to load setup checklist. Please try again." + "Retry" button |
3.7 Tab: Enrollment (NEW)
Purpose
View and manage all students enrolled in this semester. Provides at-a-glance enrollment visibility without navigating to Student Management.
Data Displayed
Summary bar (horizontal bar above table): "X students enrolled | Y in Level 0 | Z in Level 1 | ... | W in Year 2"
Source: counts from user_link_level_tag grouped by level_tag_id where semester_id = this semester.
Filter bar (standard pattern from 01-global-patterns.md Section 4.2):
| Filter | Type | Options |
|---|---|---|
| Search | Text input | Filters by student name or email |
| Level | Dropdown | All / Level 0 / Level 1 / Level 2 / Level 3 / Level 4 / Year 2 (from level_tag table) |
| TA | Dropdown | All / [TA names] (derived from group membership: group_members --> group_name --> assigned TA) |
| Status | Dropdown | All / Enrolled (user_semester_status = 1) / Pass (user_semester_status = 2) / Fail (user_semester_status = 0) |
| Subscription Status | Dropdown | All / Active / Past Due / Cancelled / No Subscription (from subscriptions table or Stripe status) |
Data table:
| Column | Source | Sortable | Filterable |
|---|---|---|---|
| Student Name | users.name via user_link_level_tag.user_id --> users |
Yes (default: alphabetical) | Yes (search in filter bar) |
| Level | level_tag.name via user_link_level_tag.level_tag_id |
Yes | Yes (dropdown in filter bar) |
| TA | Derived: user_link_level_tag.user_id --> group_members.user_id --> group_name --> assigned TA name |
Yes | Yes (dropdown in filter bar) |
| Status | user_link_level_tag.user_semester_status: 0 = Fail (red badge), 1 = Enrolled (blue badge), 2 = Pass (green badge) |
Yes | Yes (dropdown in filter bar) |
| Submissions | Count of student_submitted_assessment where user_id = this student AND semester matches (via assessment --> semester relationship) |
Yes | No |
| Submission Progress | Computed: submissions count / expected count (expected = number of weeks elapsed in semester, capped at total assessment prompts for this level) | No | No (displayed as "X/Y" with mini progress bar) |
| Subscription Status | subscriptions.status where user matches, or Stripe API lookup if no local record |
Yes | Yes (dropdown in filter bar) |
Pagination: Standard pagination (01-global-patterns.md Section 4.1): 25 records per page.
Actions
| Action | Trigger | Permission | Behavior | Confirmation |
|---|---|---|---|---|
| View Student | Student name click | All | Navigates to Student Detail Page (03-student-management.md), default tab | No |
| Enroll Student (NEW) | "Enroll Student" button (top-right) | Admin | Opens modal: Student search autocomplete (searches users by name/email, excludes already-enrolled students) --> Level selector dropdown (from level_tag table) --> Optional: Core enrollment toggle (is_core_enrollment). On save: creates user_link_level_tag record with semester_id, user_id, level_tag_id, user_semester_status = 1. Toast: "[Student name] enrolled in [Semester] at [Level]." |
No |
| Remove Enrollment | Remove icon on row (rightmost column, appears on hover) | Admin | Destructive confirmation: "Remove [student name] from [semester name]? This will delete their enrollment record but not affect their account or subscription." On confirm: deletes user_link_level_tag record. Toast: "[Student name] removed from [Semester]." |
Destructive |
| Bulk Assign TA | Checkbox selection (leftmost column) + "Assign TA" button (appears in bulk action bar above table) | Admin | TA selector dropdown appears in bulk action bar. Select TA --> confirmation: "Assign [N] students to [TA name]?" On confirm: updates group_members records to assign selected students to the TA's group. Toast: "[N] students assigned to [TA name]." |
Yes (confirmation modal) |
| Export | "Export" button (top-right, secondary) | Admin | Downloads CSV of current filtered/sorted view with all visible columns | No |
States
| State | Display |
|---|---|
| Has students | Summary bar + filter bar + data table |
| No students | Summary bar shows "0 students enrolled". Empty state below: "No students enrolled in [Semester Name]." + "Enroll Student" button |
| Filtered -- no results | "No students match your filters." + "Clear filters" link |
| Loading | Skeleton summary bar + skeleton data table |
| Error | "Unable to load enrollment data. Please try again." + "Retry" button |
3.8 Tab: Close Workflow (NEW)
Gated workflow -- each step must complete before the next unlocks. Directly addresses the semester close pain point where payments were set up before promotions were finalized (WS2 billing discovery finding). Reduces WF3 from 8+ screens / 40-70 clicks / 3 external tools to 4-6 screens / 15-25 clicks / 0 external tools.
Layout
Vertical stepper with 5 steps. Each step is a collapsible section:
- Completed steps: green checkmark icon, collapsed with summary visible, expandable to review
- Current step: expanded with full content, blue active indicator
- Locked steps: lock icon, collapsed, gray text, not expandable until prerequisite met
- Step numbers shown in circles (1-5) connected by a vertical line
Inline Documentation Block (01-global-patterns.md Section 6.3)
Collapsible "How does this work?" block at top of tab:
"This workflow guides you through end-of-semester tasks in order. Each step must be completed before the next becomes available. Steps 3 and 4 can run in parallel after Step 2 is complete. You can override gates if needed by clicking the lock icon on a locked step."
Step 1: Review EOC Assessments
Prerequisite: None (always available when Close Workflow tab is accessed) Purpose: Review end-of-course assessment results for all students and determine pass/fail.
Data table:
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Student Name | users.name via user_link_level_tag.user_id |
Yes (default: alphabetical) | Clickable --> Student Detail Page |
| Level | level_tag.name via user_link_level_tag.level_tag_id |
Yes | Level badge |
| Submissions Count | Count of student_submitted_assessment for this student in this semester |
Yes | Number |
| Final Grade | Computed: average of student_submitted_assessment.marks for this student in this semester, or teacher-assigned override value |
Yes | Number (e.g., "3.8") |
| Meets Criteria? | Computed: submissions count >= 12 AND final grade >= 3.5 | Yes | Badge: "Yes" (green) / "No" (red) |
| EOC Result | Admin-set or computed: Pass / Fail / Pending / Override | Yes | Badge: Pass (green) / Fail (red) / Pending (amber) / Override (blue) |
| Reason (if Override) | Admin-entered text | No | Shown inline when EOC Result = Override |
Filter bar:
| Filter | Type | Options |
|---|---|---|
| Level | Dropdown | All / Level 0 / Level 1 / Level 2 / Level 3 / Level 4 / Year 2 |
| Meets Criteria | Dropdown | All / Yes / No |
| EOC Result | Dropdown | All / Pass / Fail / Pending / Override |
Actions:
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Set EOC Result | Dropdown per student row (Pass / Fail) | Admin | Updates the student's EOC result for this semester. Sets user_link_level_tag.user_semester_status to 2 (pass) or 0 (fail). Toast: "[Student] set to [Pass/Fail]." |
| Override | "Override" button per student row | Admin | Opens inline form: Result (Pass/Fail dropdown) + Reason (text field, required). Creates override record. Blue "Override" badge replaces computed result. Addresses edge cases: teacher discretion, semester length variation, sub-3.5 grades on submission 12+. |
| Bulk: Set All Meeting Criteria to Pass | "Set All Meeting Criteria to Pass" button above table | Admin | Confirmation: "Set [N] students meeting criteria to Pass? Students not meeting criteria will remain Pending." On confirm: bulk updates all students where Meets Criteria = Yes to EOC Result = Pass. Toast: "[N] students set to Pass." |
| Mark Step Complete | "Mark Step 1 Complete" button at bottom of step | Admin | Blocked if any students have Pending result: button disabled with tooltip "X students still have Pending results. Resolve all before completing." When all resolved: confirmation "Mark Step 1 complete? Step 2 will be unlocked." On confirm: step marked complete, Step 2 unlocked. |
Completion criteria: All enrolled students have an EOC result of Pass, Fail, or Override. No "Pending" results remain.
Gate: Step 2 unlocked when Step 1 marked complete.
Step 2: Confirm Promotions
Prerequisite: Step 1 complete Purpose: Confirm which passed students will continue to the next semester and assign their next level.
Data table (shows only students who passed in Step 1):
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Student Name | From Step 1 passed/override-pass students | Yes | Clickable --> Student Detail Page |
| Current Level | level_tag.name from current enrollment |
Yes | Level badge |
| Next Level | Computed: Level 0 --> Level 1, Level 1 --> Level 2, Level 2 --> Level 3, Level 3 --> Level 4, Level 4 --> Year 2. Year 2 --> "Year 2 (continuing)" | No | Level badge (computed, not editable -- follows fixed progression per business rule #2 in 01-global-patterns.md Section 7) |
| Continuing? | Admin-set: Yes / No / Pending | Yes | Badge: Yes (green) / No (gray) / Pending (amber) |
| Has Active Subscription? | subscriptions.status for this student (or Stripe API lookup) |
Yes | Badge: Active (green) / Past Due (orange) / Cancelled (gray) / None (red) |
| Leave Reason (if No) | Admin-entered text | No | Shown inline when Continuing = No |
Filter bar:
| Filter | Type | Options |
|---|---|---|
| Level | Dropdown | All / Level 0-4 / Year 2 |
| Decision | Dropdown | All / Continuing / Leaving / Pending |
| Subscription | Dropdown | All / Active / Past Due / Cancelled / None |
Actions:
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Mark Continuing | "Yes" button per student row | Admin | Sets student as Continuing. Updates next level assignment. Toast: "[Student] marked as continuing to [Next Level]." |
| Mark Leaving | "No" button per student row | Admin | Opens inline Leave Reason text field (optional). Sets student as Leaving. Toast: "[Student] marked as leaving." |
| Bulk: Mark All as Continuing | "Mark All as Continuing" button above table | Admin | Confirmation: "Mark all [N] passed students as Continuing? You can change individual decisions afterward." On confirm: sets all Pending students to Continuing. |
| Bulk: Mark All as Leaving | "Mark All as Leaving" button above table | Admin | Confirmation: "Mark all [N] passed students as Leaving?" On confirm: sets all Pending students to Leaving. |
| Mark Step Complete | "Mark Step 2 Complete" button at bottom | Admin | Blocked if any students are Pending: button disabled with tooltip "X students still have Pending decisions. Resolve all before completing." When all resolved: confirmation "Mark Step 2 complete? This finalizes promotions. Steps 3 and 4 will be unlocked." On confirm: step marked complete. |
Completion criteria: All passed students have a Continuing or Leaving decision. No "Pending" decisions remain.
Gate: Step 3 AND Step 4 unlocked when Step 2 marked complete. This is the promotion gate from WS2 -- billing cannot proceed until promotions are finalized. This directly prevents the current pain point where payments are set up before promotion decisions are finalized.
Step 3: Bulk Payment Setup
Prerequisite: Step 2 complete (promotions finalized) Purpose: Create or renew Stripe subscriptions for continuing students. Gated behind Step 2 to prevent the current pain point of setting up payments before knowing who is continuing.
Data table (shows only students marked as Continuing in Step 2):
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Student Name | From Step 2 continuing students | Yes | Clickable --> Student Detail > Payments tab |
| Current Plan | payment_plans.name via subscriptions.payment_plan_id for current subscription |
Yes | Plan name or "No plan" |
| Subscription Status | subscriptions.status or Stripe status |
Yes | Badge: Active (green) / Past Due (orange) / Cancelled (gray) / None (red) |
| Action Needed | Computed: if no subscription --> "New subscription"; if subscription active but plan changing --> "Renew"; if subscription already active and plan unchanged --> "Already active"; if no subscription and no payment method --> "No subscription" | Yes | Badge: New (blue) / Renew (amber) / Already Active (green) / No Subscription (red) |
| Family Plan? | family_members record exists for this user |
No | Badge: Yes (blue) / -- (if no) |
| Scholarship? | student_scholarships record with active renewal_status for this user |
No | Badge: "50% off" or specific tier / -- (if none) |
| Payment Action | Admin-set or auto | No | "Created" / "Renewed" / "Skipped" / "Pending" |
Actions:
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Create Subscription | "Create" button per student row (for students needing new subscription) | Admin | Opens modal: Plan selector (dropdown from payment_plans), auto-applies family discount if family_members record exists, auto-applies scholarship coupon if student_scholarships record exists. On save: creates Stripe subscription via API, creates local subscriptions record. Toast: "Subscription created for [Student]." |
| Bulk: Create Subscriptions for All | "Create Subscriptions for All" button above table | Admin | Confirmation: "Create subscriptions for [N] students? Default plan will be used. Family and scholarship discounts will be applied automatically." Displays summary: "[X] new subscriptions, [Y] renewals, [Z] already active, [W] with family discount, [V] with scholarship." On confirm: batch creates/updates Stripe subscriptions. Progress bar shows completion. Results summary displayed after. |
| Handle Exception | "Handle" link per student row (for edge cases) | Admin | Navigates to Student Detail > Payments tab (03-student-management.md) for individual handling. Sets ?from=close-workflow&semester=[id] for "Return to Close Workflow" banner. |
| Skip Student | "Skip" button per student row | Admin | Opens inline Reason text field (required). Sets student as "Skipped" with reason. Toast: "[Student] skipped: [reason]." Skipped students excluded from completion count but listed in Step 5 exceptions. |
| Mark Step Complete | "Mark Step 3 Complete" button at bottom | Admin | Blocked if students have "Pending" payment action (excluding skipped): button disabled with tooltip "X students still need payment setup." When all resolved: confirmation "Mark Step 3 complete?" |
Completion criteria: All continuing students have an active or scheduled subscription, or are marked as "Skipped" with a reason.
Step 4: Handle Leavers
Prerequisite: Step 2 complete (can run in parallel with Step 3) Purpose: Deactivate accounts and cancel subscriptions for non-continuing students.
Data table (shows only students marked as Leaving in Step 2):
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Student Name | From Step 2 leaving students | Yes | Clickable --> Student Detail Page |
| Has Active Subscription? | subscriptions.status or Stripe status |
Yes | Badge: Active (green) / Past Due (orange) / None (gray) / Already Cancelled (gray) |
| Account Status | users.user_activation_status |
Yes | Badge: Active (user_activation_status = 1, green) / Deactivated (user_activation_status = 0, gray) |
| Action | Computed: if subscription active AND account active --> "Cancel & Deactivate"; if subscription not active AND account active --> "Deactivate Only"; if already handled --> "Already Handled" | No | Badge describing needed action |
| Handled? | Admin-set | No | Badge: Yes (green) / No (amber) |
Actions:
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Linked Deactivation | "Cancel & Deactivate" button per student row (for students with active subscription + active account) | Admin | Uses linked deactivation pattern (01-global-patterns.md Section 7, rule #11): single action that cancels Stripe subscription AND deactivates account. Confirmation: "This will cancel [student name]'s Stripe subscription at the end of the current billing period and deactivate their account. They will lose access to all content immediately." On confirm: calls Stripe cancel subscription API (cancel_at_period_end=true), sets users.user_activation_status = 0, marks as handled. Toast: "[Student] deactivated and subscription cancelled." |
| Deactivate Only | "Deactivate" button per student row (for students with no active subscription but active account) | Admin | Confirmation: "Deactivate [student name]? They will no longer be able to access the app." On confirm: sets users.user_activation_status = 0, marks as handled. Toast: "[Student] deactivated." |
| Bulk: Deactivate All Leavers | "Deactivate All Leavers" button above table | Admin | Confirmation: "Deactivate all [N] leaving students? [X] active subscriptions will be cancelled. [Y] accounts will be deactivated. This cannot be easily undone." On confirm: batch processes linked deactivation for all. Progress bar shows completion. Results summary displayed after. |
| Mark as Already Handled | "Already Handled" checkbox per student row | Admin | For students who were already deactivated or had subscriptions cancelled before the close workflow began. Marks as handled without taking any action. |
| Mark Step Complete | "Mark Step 4 Complete" button at bottom | Admin | Blocked if any students not handled: button disabled with tooltip "X students not yet handled." When all handled: confirmation "Mark Step 4 complete?" |
Completion criteria: All leaving students are deactivated and have subscriptions cancelled (or are marked as "Already Handled").
Step 5: Verify
Prerequisite: Steps 3 AND 4 complete Purpose: Summary dashboard confirming all semester close tasks are complete. Final checkpoint before marking the semester as closed.
Summary display (read-only dashboard):
| Metric | Source | Format |
|---|---|---|
| Total Students Reviewed | Count of all students processed in Step 1 | "X students" |
| Passed | Count of students with EOC Result = Pass or Override (Pass) | "Y passed" |
| -- Promoted (Continuing) | Count of students marked Continuing in Step 2 | "Z promoted to next level" |
| -- Leaving | Count of students marked Leaving in Step 2 | "W leaving" |
| Failed | Count of students with EOC Result = Fail | "V failed" |
| Subscriptions Created/Renewed | Count of students with Payment Action = "Created" or "Renewed" in Step 3 | "A subscriptions set up" |
| Accounts Deactivated | Count of students deactivated in Step 4 | "B accounts deactivated" |
| Subscriptions Cancelled | Count of Stripe subscriptions cancelled in Step 4 | "C subscriptions cancelled" |
| Exceptions/Skipped | Count of students skipped in Step 3 + any unresolved items | "D exceptions" (with expandable list showing each exception: student name, reason, step) |
Exception Details (expandable section, shown only if exceptions > 0):
| Column | Source |
|---|---|
| Student Name | Skipped or exception student name (clickable --> Student Detail Page) |
| Step | Which step the exception occurred in |
| Reason | Admin-entered reason from Skip action |
| Resolution | "Unresolved" (amber) or "Resolved" (green, if admin manually resolved) |
Actions:
| Action | Trigger | Permission | Behavior |
|---|---|---|---|
| Review Exceptions | "Review Exceptions" link per exception | Admin | Navigates to individual Student Detail Page for unresolved items |
| Mark Exception Resolved | "Resolve" button per exception | Admin | Opens inline note field for resolution details. Marks exception as resolved. |
| Mark Semester Close Complete | "Mark Semester Close Complete" button (prominent, bottom of step) | Admin | Blocked if unresolved exceptions exist: button shows warning "X unresolved exceptions. Review before closing." (warning, not hard block -- admin can proceed). Confirmation: "Mark semester close complete for [Semester Name]? This will lock the close workflow and set the semester to closed status. This cannot be undone." On confirm: locks entire Close Workflow (all steps become read-only), sets semester status to closed (is_current = 0 if still active), records completion timestamp. Toast: "Semester [name] close complete." |
Completion: Semester status updated. Close Workflow tab shows "Completed on [date]" summary header. All steps shown in read-only mode with green checkmarks.
Gate Override
For exceptional situations where the admin needs to bypass the normal gating sequence:
| Element | Behavior |
|---|---|
| Trigger | Click the lock icon on any locked step |
| Confirmation | Modal: "Override gate on Step [X]? This step normally requires [prerequisite]. Reason for override:" + required text field |
| Logging | System log entry: "[Admin name] overrode gate on Step [X] for [Semester Name]: [reason]" -- logged to Reporting > Logs |
| Visual indicator | Overridden step shows an orange "Overridden" badge next to its title (persists even after step completion) |
| Permission | Admin only |
Close Workflow States
| State | Display |
|---|---|
| Not started | Step 1 expanded and active. Steps 2-5 locked. Message at top: "Begin semester close by reviewing EOC assessments." |
| In progress | Current step expanded with full content. Completed steps collapsed with summary (expandable to review). Locked steps show lock icon and gray text. |
| Completed | All steps show green checkmarks. Summary header: "Semester close completed on [date] by [admin name]." All steps in read-only mode (data visible, no action buttons). |
| Close not applicable | If semester phase is Setup or Active (not in close phase): informational message "Close workflow is available when the semester is in its close phase. Current phase: [Setup/Active]." Followed by note: "You can start the close workflow early if needed." Steps are accessible but show the informational message prominently. Does NOT block access entirely -- admin may need to start early. |
| Loading | Skeleton step accordion (5 collapsed blocks with pulsing animation). If a specific step involves Stripe data (Steps 3-4), shows "Loading billing data..." within that step's content area. |
| Error | Per-step error handling: if data for a step fails to load, that step shows "Unable to load data for this step. Please try again." with a Retry button. Other steps remain functional. |
4. Screen: Welcome Package
4.1 Purpose
Manage resources included in the new student welcome package for each semester. These are files (PDFs, documents, media) sent or made available to students upon enrollment. Relocated from Settings to Semester Management because welcome packages are semester-scoped.
Transition hint (01-global-patterns.md Section 6.4): "Formerly under Settings" -- shown for first 30 days after launch.
4.2 Entry Points
- Sidebar: Semester Management > Welcome Package
- Semester Hub > Setup Checklist: "Configure -->" link (with
?from=checklist&semester=[id]for return affordance)
4.3 Layout
Semester selector (dropdown at top, defaults to current/active semester) + resource list with upload capability. Uses standard Data Table pattern for the resource list.
4.4 Data Displayed
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Document Name | Resource title (admin-entered) | Yes (default: by display order) | Clickable to preview/download |
| File | File name + type icon (PDF, DOC, etc.) | No | Shows file extension badge |
| Semester | semester.name (from semester selector context) |
No | Shown if "All semesters" selected in dropdown |
| Upload Date | File upload timestamp | Yes | Formatted as "Mar 10, 2026" |
| Size | File size | Yes | Formatted as "2.4 MB" |
| Order | Display order number (determines order students see resources) | No | Editable via drag handle |
4.5 Actions
| Action | Trigger | Permission | Behavior | Confirmation |
|---|---|---|---|---|
| Upload Resource | "Upload" button (top-right) | Admin | Opens upload modal: Document Name (text), File (file picker -- accepts PDF, DOC, DOCX, PNG, JPG, MP4), Semester (pre-selected from current dropdown context). On save: uploads file, creates resource record. Toast: "[Document name] uploaded." | No |
| Edit | Edit icon on row | Admin | Opens edit modal pre-filled: Document Name (editable), File (replaceable). | No |
| Delete | Delete icon on row | Admin | Destructive confirmation: "Delete [document name]? Students will no longer be able to access this resource." | Destructive |
| Reorder | Drag handle on row (leftmost) | Admin | Drag-and-drop to reorder. Auto-saves on drop. Toast: "Order updated." | No |
| Preview/Download | Document name click | All | Opens file in browser preview (PDFs, images) or downloads (other file types) | No |
| Clone from Previous (NEW) | "Clone from [Previous Semester]" button (secondary, top-right) | Admin | Dropdown of previous semesters. Confirmation: "Clone all welcome package files from [Previous Semester]? [N] files will be copied to [Current Semester]." Creates independent copies. Toast: "Cloned [N] files from [Previous Semester]." | Yes |
4.6 States
| State | Display |
|---|---|
| Has resources | Resource list with drag handles for reordering |
| Empty | "No welcome package resources for [Semester Name]." + "Upload" button + "Clone from [Previous Semester]" button |
| Loading | Skeleton resource list |
| Error | "Unable to load welcome package. Please try again." + "Retry" button |
4.7 Role Visibility
- Admin: Full CRUD (Upload, Edit, Delete, Reorder, Clone)
- View-Only: View list + Preview/Download. No Upload, Edit, Delete, Reorder, or Clone buttons.
- TA / Support Staff: Hidden (sidebar item not visible)
5. Screen: Email Management
5.1 Purpose
Configure automated email templates for the semester. Templates define both content and trigger conditions for automated student communications (welcome emails, reminders, promotion notifications, etc.). Relocated from Settings.
Transition hint: "Formerly under Settings" -- shown for first 30 days.
5.2 Entry Points
- Sidebar: Semester Management > Email Management
- Semester Hub > Setup Checklist: "Configure -->" link (with return affordance)
- Semester Hub > Overview: "View All Emails" link in Automation section
5.3 Layout
Semester selector (dropdown at top, defaults to current/active semester) + email template list. Uses standard Data Table pattern (01-global-patterns.md Section 4.1).
5.4 Data Displayed
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Template Name | emails.name |
Yes (default: alphabetical) | Clickable --> opens editor |
| Subject | emails.subject |
Yes | Truncated to 60 chars with tooltip for full text |
| Trigger | Computed from email configuration: "On registration", "Week 1 start", "Semester end", "On promotion", etc. | Yes | Describes when the email is automatically sent |
| Semester | semester.name via emails.semester_id |
No | Shown if "All semesters" selected in dropdown |
| Status | emails.status (Active / Draft) |
Yes | Badge: Active (green) / Draft (gray) |
| Last Edited | emails.updated_at |
Yes | Formatted as "Mar 10, 2026" |
5.5 Actions
| Action | Trigger | Permission | Behavior | Confirmation |
|---|---|---|---|---|
| Create Template | "Create Template" button (top-right) | Admin | Opens email editor (modal or full-screen): Template Name (text), Subject (text), Trigger (dropdown: On Registration / Week Start / Semester End / On Promotion / On Failure / Custom Date), Body (rich text editor with template variables: {{student_name}}, {{semester_name}}, {{level}}, {{ta_name}}), Status (Active / Draft toggle). On save: creates emails record. Toast: "Template '[name]' created." |
No |
| Edit | Edit icon or row click | Admin | Opens email editor pre-filled with template data. All fields editable. | No |
| Delete | Delete icon on row | Admin | Destructive confirmation: "Delete template '[name]'? If this template is active, scheduled emails using it will not be sent." | Destructive |
| Preview | Preview icon (eye icon) on row | All | Opens preview modal (01-global-patterns.md Section 4.10, max width 800px): renders email template with sample data (e.g., {{student_name}} = "Sarah Ahmed", {{semester_name}} = current semester name). Shows rendered subject and body. |
No |
| Test Send | "Test Send" button (in editor or preview modal) | Admin | Sends the email to the logged-in admin's email address with sample data. Toast: "Test email sent to [admin email]." | No |
| Clone from Previous (NEW) | "Clone All Templates" button (secondary, top-right) | Admin | Dropdown of previous semesters. Shows count: "[Previous Semester] has [N] templates." Confirmation: "Clone all email templates from [Previous Semester]? [N] templates will be copied as Drafts." Creates independent copies with Status = Draft. Toast: "Cloned [N] templates from [Previous Semester]." | Yes |
5.6 States
| State | Display |
|---|---|
| Has templates | Template list table |
| Empty | "No email templates for [Semester Name]." + "Create Template" button + "Clone from [Previous Semester]" button |
| Filtered -- no results | "No templates match your search." + "Clear search" link |
| Loading | Skeleton data table |
| Error | "Unable to load email templates. Please try again." + "Retry" button |
5.7 Role Visibility
- Admin: Full CRUD (Create, Edit, Delete, Preview, Test Send, Clone)
- View-Only: View list + Preview only. No Create, Edit, Delete, Test Send, or Clone buttons.
- TA / Support Staff: Hidden (sidebar item not visible)
6. Screen: Tags
6.1 Purpose
Create and manage tags for user segmentation. Tags are semester-scoped and sync bidirectionally with InfusionSoft (CRM). Used for marketing segmentation, student categorization, and automated workflow triggers. Relocated from Settings.
Transition hint: "Formerly under Settings" -- shown for first 30 days.
6.2 Entry Points
- Sidebar: Semester Management > Tags
- Semester Hub > Setup Checklist: "Configure -->" link (with return affordance)
6.3 Layout
Semester selector (dropdown at top, defaults to current/active semester) + tags list. Uses standard Data Table pattern. No filter bar needed (typically <30 tags per semester).
6.4 Data Displayed
| Column | Source | Sortable | Notes |
|---|---|---|---|
| Tag Name | tags.name |
Yes (default: alphabetical) | |
| Semester | semester.name via tags.semester_id |
No | Shown if "All semesters" selected in dropdown |
| Students Tagged | Count of user-tag associations for this tag | Yes | Number (e.g., "45") |
| InfusionSoft Synced | Whether the tag exists in InfusionSoft and is in sync | No | Badge: Synced (green, checkmark) / Not Synced (red, warning icon) / Sync Pending (amber, clock icon) |
| Created | tags.created_at |
Yes | Formatted date |
6.5 Actions
| Action | Trigger | Permission | Behavior | Confirmation |
|---|---|---|---|---|
| Create Tag | "Create Tag" button (top-right) | Admin | Opens modal: Tag Name (text), Semester (pre-selected from dropdown context). On save: creates tags record AND triggers InfusionSoft API sync to create matching tag in CRM. Toast: "Tag '[name]' created and synced to InfusionSoft." If InfusionSoft sync fails: Toast (error): "Tag created locally but InfusionSoft sync failed. Retry from tag list." |
No |
| Edit | Edit icon on row | Admin | Opens modal pre-filled: Tag Name (editable). On save: updates local record AND updates InfusionSoft tag name. | No |
| Delete | Delete icon on row | Admin | Destructive confirmation: "Delete tag '[name]'? This will remove the tag from [N] students and delete it from InfusionSoft." On confirm: removes all user-tag associations, deletes tags record, deletes matching InfusionSoft tag. |
Destructive |
| Retry Sync | "Retry" link (shown only for tags with "Not Synced" status) | Admin | Re-attempts InfusionSoft API sync for this tag. Toast on success: "Tag synced to InfusionSoft." Toast on failure: "InfusionSoft sync failed. Check connection and try again." | No |
6.6 States
| State | Display |
|---|---|
| Has tags | Tags list table |
| Empty | "No tags for [Semester Name]." + "Create Tag" button |
| Loading | Skeleton data table |
| Error | "Unable to load tags. Please try again." + "Retry" button |
| InfusionSoft unavailable | Warning banner at top: "InfusionSoft connection unavailable. Tags can be created locally but will not sync until connection is restored." Tags table still shows with "Not Synced" badges. |
6.7 Role Visibility
- Admin: Full CRUD (Create, Edit, Delete, Retry Sync)
- View-Only: View list only. No Create, Edit, Delete, or Retry buttons.
- TA / Support Staff: Hidden (sidebar item not visible)
7. Screen: Operations (Bulk Actions)
7.1 Purpose
Perform bulk data operations that are semester-scoped. Provides a centralized place for high-volume administrative actions that would be tedious to perform one-by-one. Relocated from Settings. Now also includes Level 0 promotion (absorbed from dissolved Students Management screen #14 -- see 00-spec-index.md Section 4, Dissolved Screen #14 Redistribution).
Transition hint: "Formerly under Settings" -- shown for first 30 days.
7.2 Entry Points
- Sidebar: Semester Management > Operations
7.3 Layout
Action cards -- each bulk operation is a card with icon, title, description, and action button. Cards arranged in a responsive grid (2 columns on desktop, 1 on narrow screens). No data table -- this is a launcher page.
7.4 Available Operations
Card 1: Bulk Year 1 --> Year 2 Promotion
| Field | Detail |
|---|---|
| Icon | Arrow-up icon |
| Title | Bulk Year 1 --> Year 2 Promotion |
| Description | "Promote eligible students from Year 1 to Year 2. Upload a CSV with student IDs to process." |
| Action Button | "Start Promotion" |
| Permission | Admin only |
| Workflow | Click "Start Promotion" --> File picker (CSV, required columns: user_id) --> Upload + validation (checks: all user_ids exist, all are Year 1 students, none already in Year 2) --> Validation results modal showing valid/invalid rows --> Confirmation: "Promote [N] students from Year 1 to Year 2?" --> Processing with progress bar --> Results summary: "[X] promoted successfully, [Y] errors" with downloadable error log |
Card 2: Bulk User Registration
| Field | Detail |
|---|---|
| Icon | Users-plus icon |
| Title | Bulk User Registration |
| Description | "Register multiple students at once. Upload a CSV with student data (name, email, level)." |
| Action Button | "Start Registration" |
| Permission | Admin only |
| Workflow | Click "Start Registration" --> File picker (CSV, required columns: name, email, level) --> Upload + validation (checks: email format valid, no duplicate emails, level values valid) --> Validation results modal --> Semester selector (which semester to register students in) --> Confirmation: "Register [N] students for [Semester Name]?" --> Processing with progress bar --> Results summary: "[X] registered successfully, [Y] errors" with downloadable error log. Auto-generates passwords (4 characters, lowercase -- per business rule #10 in 01-global-patterns.md Section 7) |
Card 3: Upload Backend Resources
| Field | Detail |
|---|---|
| Icon | Upload-cloud icon |
| Title | Upload Backend Resources |
| Description | "Upload resources to the backend for administrative use (not student-facing)." |
| Action Button | "Upload Resources" |
| Permission | Admin only |
| Workflow | Click "Upload Resources" --> File picker (multiple files accepted) --> Semester selector --> Confirmation --> Upload with progress bar --> Results: "[X] files uploaded successfully." |
Card 4: Data Migration
| Field | Detail |
|---|---|
| Icon | Database icon |
| Title | Data Migration |
| Description | "Migrate data between databases. Use for semester transitions or data cleanup." |
| Action Button | "Start Migration" |
| Permission | Admin only |
| Workflow | Click "Start Migration" --> Configuration form (source, destination, data types to migrate) --> Dry run preview showing what will be migrated --> Confirmation: "Migrate [N] records? This will overwrite existing data in the destination." --> Processing with progress bar --> Results summary |
Card 5: Level 0 Promotion (NEW -- from dissolved #14)
| Field | Detail |
|---|---|
| Icon | Arrow-right icon |
| Title | Level 0 Promotion |
| Description | "Promote Level 0 students who did not submit assessments. These students bypass the normal EOC assessment process." |
| Action Button | "Start Promotion" |
| Permission | Admin only |
| Workflow | Click "Start Promotion" --> Semester selector (defaults to current active semester) --> Shows list of Level 0 students who have NOT submitted any assessments for the selected semester (query: user_link_level_tag where level_tag_id = Level 0 AND semester_id = selected AND user has no records in student_submitted_assessment for this semester) --> Admin can select/deselect individual students --> Confirmation: "Promote [N] Level 0 students to Level 1?" --> Processing --> Results: "[X] promoted to Level 1 successfully." Updates user_link_level_tag.level_tag_id to Level 1 for promoted students. |
7.5 States
| State | Display |
|---|---|
| Default | All operation cards shown in grid, ready for use |
| In progress | Active operation card shows progress bar with percentage. Other cards remain clickable (operations are independent). Processing card shows "Cancel" button if cancellation is safe. |
| Completed | Active card shows result summary with green success banner: "[X] records processed successfully." If errors: amber banner: "[X] successful, [Y] errors." + "Download Error Log" link (CSV with error details per row). |
| Error | Active card shows red error banner: "Operation failed: [error message]." + "Retry" button + "Download Error Log" link |
| Validation failed | After CSV upload: modal showing validation issues. Table with: Row Number, Field, Issue (e.g., "Row 15: email 'invalid' is not a valid email format"). "Fix and Re-upload" button. |
7.6 Role Visibility
- Admin: All operation cards visible and actionable
- View-Only / TA / Support Staff: Hidden (sidebar item not visible -- bulk operations are admin-only)
8. Cross-Domain Integration Points
This section documents how Semester Management connects to other domains. Each integration is specified in detail in the target domain's spec document; this section provides a summary for reference.
8.1 Dashboard (02-dashboard.md)
| Dashboard Element | Links To | Data Source |
|---|---|---|
| Phase prompt tile | Semester Hub Page (appropriate tab based on phase) | semester.is_current, semester.start_date, semester.end_date, computed phase |
| Setup progress indicator | Semester Hub > Setup Checklist tab | Checklist completion computation |
| "Semester close due" alert | Semester Hub > Close Workflow tab | Computed from semester.end_date proximity |
8.2 Student Detail Page (03-student-management.md)
| Integration | Direction | Details |
|---|---|---|
| Semester History tab | Student --> Semester | Student Detail shows semester enrollment history with semester names clickable --> Semester Hub |
| Enrollment | Semester --> Student | Enrollment tab student names clickable --> Student Detail Page |
| Close Workflow | Semester --> Student | Steps 1-4 student names clickable --> Student Detail Page; Step 3 "Handle Exception" --> Student Detail > Payments tab |
8.3 Content Domain (05-content.md)
| Integration | Direction | Details |
|---|---|---|
| Setup Checklist deep links | Semester --> Content | "Configure -->" links navigate to Content screens with ?semester=[id]&level=[level] pre-filtered |
| Return to Checklist | Content --> Semester | "Return to Setup Checklist" banner on Content screens when ?from=checklist param present |
| Content scoping | Shared | All content tables reference semester_id -- content is always scoped to a semester (business rule #6) |
8.4 Scheduling Domain (06-scheduling.md)
| Integration | Direction | Details |
|---|---|---|
| Live Sessions link | Semester --> Scheduling | Setup Checklist "Configure -->" for Live Sessions navigates to Scheduling > Live Sessions with semester filter |
| TA Schedules link | Semester --> Scheduling | Setup Checklist "Configure -->" for TA Schedules navigates to Scheduling > TA Schedules |
| Holidays link | Semester --> Scheduling | Setup Checklist "Configure -->" for Holidays navigates to Scheduling > Holidays |
8.5 Teacher Management Domain (07-teacher-management.md)
| Integration | Direction | Details |
|---|---|---|
| Teacher Assignment link | Semester --> Teacher | Setup Checklist "Configure -->" for Teacher Assignments navigates to Teacher Management > Teacher Assignment Criteria |
| Enrollment TA filter | Shared | Enrollment tab TA column and filter reference TA data from Teacher Management |
8.6 Billing & Payments Domain (08-billing-payments.md)
| Integration | Direction | Details |
|---|---|---|
| Close Workflow Step 3 | Semester --> Billing | Bulk payment setup creates Stripe subscriptions using payment_plans, respects family_members and student_scholarships discounts |
| Close Workflow Step 4 | Semester --> Billing | Linked deactivation cancels Stripe subscriptions during leaver handling |
| Enrollment subscription column | Billing --> Semester | Enrollment tab shows subscription status from subscriptions table |
9. Assumptions and Open Questions
This domain relies on several assumptions documented in 00-spec-index.md. Summary of semester-management-specific assumptions:
| ID | Assumption | Impact on This Spec | Validation Needed |
|---|---|---|---|
| OQ5 | Content cloning creates independent copies (not linked) | Clone from Previous features in Setup Checklist (Section 3.6), Welcome Package (Section 4), Email Management (Section 5), and Tags are all independent copies. No cross-semester versioning. | Confirm with admin: does cloned content ever need to stay linked to its source? |
| OQ7 | Immediate subscription creation (not Subscription Schedules) | Close Workflow Step 3 creates subscriptions immediately rather than scheduling future starts. Admin can backdate if needed. | Confirm: should subscriptions start immediately or be scheduled for next semester start date? |
New questions raised by this spec (to be logged in 00-spec-index.md if not already covered):
- SQ1: How many checklist items per semester are typically applicable? If many items are consistently N/A, consider configurable templates per semester type. Assumed: all items applicable by default.
- SQ2: Should the Close Workflow allow partial re-opening after completion (e.g., to handle a late-arriving student)? Assumed: no -- once complete, the workflow is locked. Individual student adjustments can be made via Student Detail Page.
- SQ3: Should the auto-transition feature (Overview tab) support registration auto-close in addition to semester activation/deactivation? Assumed: no -- registration close is a separate manual decision.
- SQ4: How should the Setup Checklist handle content that spans multiple levels (e.g., a resource available to all levels)? Assumed: content appears under each applicable level item (may result in some double-counting in progress, but avoids missing items).
- SQ5: Should the Close Workflow Step 1 "Meets Criteria" computation be configurable (e.g., different thresholds per level or semester)? Assumed: fixed at submissions >= 12 AND grade >= 3.5 per current business rules. Configuration would add complexity.