SafePath Training — UI Pages Implementation Plan
Overview
The SafePath Training module backend is fully built across 6 phases (1A–1F) with 45 API routes, complete TypeScript types in src/types/safepath.ts, and frontend API client functions in src/services/api/safepath.api.ts. However, no UI pages, routes, or sidebar navigation exist yet.
This document defines a phased approach to build the complete SafePath UI, following existing patterns from ChemIQ, AdminHQ, and Plan Builder modules.
Existing Infrastructure
| Layer | Status | Location |
|---|---|---|
| Backend API | Complete (45 routes) | tellus-ehs-hazcom-service/app/api/v1/safepath/ |
| TypeScript types | Complete (35+ interfaces) | tellus-ehs-hazcom-ui/src/types/safepath.ts |
| API client functions | Complete (28+ functions) | tellus-ehs-hazcom-ui/src/services/api/safepath.api.ts |
| UI pages | Not started | — |
| Sidebar integration | Not started | — |
| Route registration | Not started | — |
UI Patterns to Follow
All SafePath pages must follow established patterns:
- Route registration: Lazy-loaded via
const XPage = lazy(() => import(...))inApp.tsx, wrapped in<ProtectedRoute> - Page wrapper:
<MainLayout>component (acceptschildrenand optionaldisableScroll) - Sidebar: Dedicated
SidebarSafePath.tsxcomponent (pattern fromSidebarChemIQ.tsx) with feature code → icon/path/permission mapping - Auth state:
const { user, currentSite, accessToken } = useAppSelector((state) => state.auth) - Token:
const token = accessToken?.replace(/"/g, '') || '' - IDs:
const companyId = user?.last_company_id || '',const userId = user?.user_id || '' - Data fetching:
useCallback+useEffectpattern with loading/error/empty states - Icons: Lucide React
- Notifications: React Hot Toast
- Permissions:
<PermissionGate>component for conditional rendering
Phase Dependency Graph
Phase 2A (Foundation) ──┬──→ Phase 2B (Dashboard)
├──→ Phase 2C (Course List + Detail) ──→ Phase 2D (Course Editor)
├──→ Phase 2E (Matrix & Reports)
├──→ Phase 2F (Assignments & Certifications)
└──→ Phase 2G (Quickstart)
│
▼
Phase 2H (Polish)
Phases 2B–2G can run in parallel after 2A. Phase 2D depends on 2C. Phase 2H depends on all others.
Phase 2A: Foundation — Routing, Sidebar & Skeleton Pages
Goal: Wire up the entire SafePath section so every page is navigable from the sidebar, even with placeholder content. Establishes URL structure and proves routing/sidebar integration end-to-end.
Files to Create
1. src/components/sidebar/SidebarSafePath.tsx (NEW)
Sidebar section component following the SidebarChemIQ.tsx pattern exactly.
- Props:
features,isExpanded,isInSafePathPath,isPathActive,onToggle,onItemClick - Module icon:
GraduationCap(from lucide-react, already inSidebar.tsxicon map) - Active color:
accent-coral(SafePath module color) or fallback toaccent-pink - Feature code → navigation mapping:
| Feature Code | Icon | Path | Permission |
|---|---|---|---|
DASHBOARD | LayoutDashboard | /safepath/dashboard | safepath:dashboard:* |
COURSES | BookOpen | /safepath/courses | safepath:courses:* |
ASSIGNMENTS | ClipboardList | /safepath/assignments | safepath:assignments:* |
CERTIFICATIONS | Award | /safepath/certifications | safepath:certifications:* |
MATRIX | Grid3X3 | /safepath/matrix | safepath:matrix:* |
REPORTS | FileBarChart | /safepath/reports | safepath:reports:* |
QUICKSTART | Rocket | /safepath/quickstart | safepath:quickstart:* |
2. Skeleton Page Files (9 new files)
Each skeleton page is a default-export React component wrapping <MainLayout> with a coral gradient header and placeholder body. Pattern:
import React from 'react';
import { MainLayout } from '../../../components/MainLayout';
import { GraduationCap } from 'lucide-react';
const SafePathDashboardPage: React.FC = () => {
return (
<MainLayout>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-6">
{/* Page header */}
<div className="bg-gradient-to-r from-pink-500 via-rose-500 to-orange-400 rounded-xl p-6 text-white">
<div className="flex items-center gap-3">
<GraduationCap className="h-7 w-7" />
<div>
<h1 className="text-2xl font-bold">Training Dashboard</h1>
<p className="text-pink-100 text-sm mt-1">SafePath Training Management</p>
</div>
</div>
</div>
{/* Placeholder content */}
<div className="bg-white rounded-lg border border-border-light p-12 text-center">
<GraduationCap className="h-12 w-12 text-gray-300 mx-auto mb-4" />
<p className="text-text-muted text-lg">Coming soon</p>
<p className="text-text-muted text-sm mt-1">This page is under development.</p>
</div>
</div>
</MainLayout>
);
};
export default SafePathDashboardPage;
| # | File Path | Page Title |
|---|---|---|
| 1 | src/pages/safepath/dashboard/index.tsx | Training Dashboard |
| 2 | src/pages/safepath/courses/index.tsx | Course Library |
| 3 | src/pages/safepath/courses/CourseDetailPage.tsx | Course Details |
| 4 | src/pages/safepath/courses/CourseEditorPage.tsx | Course Editor |
| 5 | src/pages/safepath/assignments/index.tsx | Training Assignments |
| 6 | src/pages/safepath/certifications/index.tsx | Certifications |
| 7 | src/pages/safepath/matrix/index.tsx | Training Matrix |
| 8 | src/pages/safepath/reports/index.tsx | Training Reports |
| 9 | src/pages/safepath/quickstart/index.tsx | Quickstart Wizard |
Files to Modify
3. src/components/Sidebar.tsx
Add SafePath module support:
// Import
import { SidebarSafePath } from './sidebar/SidebarSafePath';
// State (add alongside existing module states)
const [isSafePathExpanded, setIsSafePathExpanded] = useState(false);
// Module extraction (add alongside existing module lookups)
const safePathModule = modules.find(m => m.module_code === 'SAFEPATH');
const safePathFeatures = safePathModule?.features || [];
// Auto-expand effect (add alongside existing auto-expand effects)
React.useEffect(() => {
if (location.pathname.startsWith('/safepath')) {
setIsSafePathExpanded(true);
}
}, [location.pathname]);
// Render (add after Plan Builder section, before generic module loop)
<PermissionGate permission="safepath:*">
<SidebarSafePath
features={safePathFeatures}
isExpanded={isSafePathExpanded}
isInSafePathPath={location.pathname.startsWith('/safepath')}
isPathActive={isPathActive}
onToggle={() => setIsSafePathExpanded(!isSafePathExpanded)}
onItemClick={() => setIsMobileOpen(false)}
/>
</PermissionGate>
4. src/App.tsx
Add lazy imports and routes:
// Lazy-loaded SafePath pages (add after Plan Builder lazy imports)
const SafePathDashboardPage = lazy(() => import('./pages/safepath/dashboard'));
const SafePathCoursesPage = lazy(() => import('./pages/safepath/courses'));
const CourseDetailPage = lazy(() => import('./pages/safepath/courses/CourseDetailPage'));
const CourseEditorPage = lazy(() => import('./pages/safepath/courses/CourseEditorPage'));
const SafePathAssignmentsPage = lazy(() => import('./pages/safepath/assignments'));
const SafePathCertificationsPage = lazy(() => import('./pages/safepath/certifications'));
const SafePathMatrixPage = lazy(() => import('./pages/safepath/matrix'));
const SafePathReportsPage = lazy(() => import('./pages/safepath/reports'));
const SafePathQuickstartPage = lazy(() => import('./pages/safepath/quickstart'));
// Routes (add after Plan Builder routes, before AdminHQ routes)
{/* SafePath Training Routes */}
<Route path="/safepath" element={<Navigate to="/safepath/dashboard" replace />} />
<Route path="/safepath/dashboard" element={<ProtectedRoute><SafePathDashboardPage /></ProtectedRoute>} />
<Route path="/safepath/courses" element={<ProtectedRoute><SafePathCoursesPage /></ProtectedRoute>} />
<Route path="/safepath/courses/new" element={<ProtectedRoute><CourseEditorPage /></ProtectedRoute>} />
<Route path="/safepath/courses/:courseId" element={<ProtectedRoute><CourseDetailPage /></ProtectedRoute>} />
<Route path="/safepath/courses/:courseId/edit" element={<ProtectedRoute><CourseEditorPage /></ProtectedRoute>} />
<Route path="/safepath/assignments" element={<ProtectedRoute><SafePathAssignmentsPage /></ProtectedRoute>} />
<Route path="/safepath/certifications" element={<ProtectedRoute><SafePathCertificationsPage /></ProtectedRoute>} />
<Route path="/safepath/matrix" element={<ProtectedRoute><SafePathMatrixPage /></ProtectedRoute>} />
<Route path="/safepath/reports" element={<ProtectedRoute><SafePathReportsPage /></ProtectedRoute>} />
<Route path="/safepath/quickstart" element={<ProtectedRoute><SafePathQuickstartPage /></ProtectedRoute>} />
Verification Checklist — Phase 2A
- App compiles without TypeScript errors
- Navigating to
/safepathredirects to/safepath/dashboard - All 10 SafePath routes render their skeleton pages
- Sidebar shows "SafePath" section with GraduationCap icon
- Sidebar auto-expands when URL starts with
/safepath - Each sidebar item navigates to correct route
- Active sidebar item highlights correctly
- Permission gating: section hidden if user lacks
safepath:*permission - Lazy loading works (PageLoader spinner appears during load)
Dependencies
None (this is the foundation phase).
Phase 2B: Dashboard Pages (Employee + Admin)
Goal: Build the dual-view Training Dashboard — Employee Dashboard for regular users showing personal training status, and Admin Dashboard for coordinators/admins showing team compliance metrics.
Files to Create
1. src/pages/safepath/dashboard/components/StatCard.tsx (NEW)
Reusable stat card component. Props: { icon: LucideIcon, label: string, value: number | string, color: string, subtitle?: string, onClick?: () => void }.
Styled as a rounded card with icon, large value, label text, and optional click handler for navigation.
2. src/pages/safepath/dashboard/components/EmployeeDashboard.tsx (NEW)
Employee-facing dashboard using getMyDashboard() API.
Sections:
- Assignment Status Summary: 6 stat cards (pending, in_progress, completed, overdue, expired, total) from
AssignmentStatusCounts - Upcoming Due: Table of
MyAssignmentItem[]— course title, due date, priority badge, progress bar, status badge - Overdue Assignments: Red-accented alert list with days-overdue count
- Recent Completions: Green-accented list of recently completed courses
- Expiring Certifications: Warning list of
MyCertificationItem[]with days-until-expiry countdown - Total Hours: Stat card showing
total_hours_completed
Data fetching: useCallback + useEffect with getMyDashboard(token, userId, companyId)
3. src/pages/safepath/dashboard/components/AdminDashboard.tsx (NEW)
Admin-facing dashboard using getAdminDashboard() API.
Sections:
- Company Summary: Assignment count cards from
company_summary - Completion Rates: 30-day and 90-day completion rate cards with progress bars
- Team Compliance Table: Sortable table of
TeamComplianceItem[]— employee name, email, assigned/completed/overdue counts, compliance percentage bar - Course Completions Table:
CourseCompletionItem[]with completion rates, average scores - Site Compliance: Bar chart of
SiteComplianceItem[](if multiple sites) - Overdue Alerts: Priority-sorted list of
OverdueAlertItem[](top 20) - Certification Summary: Cards for
certifications_expiring_30dandcertifications_expired - Site Filter: Dropdown that passes
site_idtogetAdminDashboard()
Files to Modify
4. src/pages/safepath/dashboard/index.tsx (REPLACE skeleton)
- Detects admin vs employee via permissions or role check
- Shows tab switcher for admin users (Employee View / Admin View)
- Renders
<EmployeeDashboard>or<AdminDashboard>accordingly - Standard auth state extraction pattern
Verification Checklist — Phase 2B
- Dashboard loads without errors
- Employee view shows assignment status, upcoming due, overdue, certifications
- Admin view shows team compliance, course completions, site compliance, overdue alerts
- Site filter on admin dashboard triggers re-fetch
- Loading spinner during data fetch
- Error state with retry button on API failure
- Empty states with meaningful messages
- Tab switching works for admin users
- Stat cards show correct numbers
Dependencies
Phase 2A (routing and skeleton pages).
Phase 2C: Course Library — List and Detail Views
Goal: Build the read-only course browsing experience: filterable course list and full course detail page with lessons and quizzes.
Files to Create
1. src/pages/safepath/courses/components/CourseStatusBadge.tsx (NEW)
Small component rendering status as colored pill badge: Draft (gray), Published (green), Archived (amber).
2. src/pages/safepath/courses/components/CourseListTable.tsx (NEW)
Course list using getCourses() API.
Features:
- Filter Bar: Search input (title), status dropdown (all/draft/published/archived), category dropdown (from
getCategories()) - Table:
CourseListItem[]with title, category, OSHA standard ref, duration,<CourseStatusBadge>, version number, lesson/quiz/assignment counts, dates - Sort: Clickable column headers (title, status, created_at)
- Pagination: Page controls (previous/next, page indicator)
- Actions: "Create Course" button navigates to
/safepath/courses/new - Row click: Navigates to
/safepath/courses/:courseId
3. src/pages/safepath/courses/components/LessonCard.tsx (NEW)
Renders a lesson in the course detail view. Shows: lesson type icon (video/pdf/slides/text/external_link), title, sort order, completion threshold, asset count. Read-only.
4. src/pages/safepath/courses/components/QuizCard.tsx (NEW)
Renders a quiz with questions in the detail view. Shows: quiz title, question list with type indicators (MCQ/true-false/matching), option list, explanations. Read-only.
Files to Modify
5. src/pages/safepath/courses/index.tsx (REPLACE skeleton)
- Coral gradient header with "Create Course" button
- Renders
<CourseListTable>as main content
6. src/pages/safepath/courses/CourseDetailPage.tsx (REPLACE skeleton)
- Extracts
courseIdfromuseParams() - Fetches
getCourse(token, userId, companyId, courseId) - Displays: course metadata, lessons via
<LessonCard>, quizzes via<QuizCard> - Action Bar (permission-gated, status-dependent):
- Draft → "Publish" button (calls
publishCourse()) - Published → "Archive" + "New Version" buttons
- Archived → "New Version" button
- Draft → "Publish" button (calls
- "Edit" button →
/safepath/courses/:courseId/edit - Back button →
/safepath/courses
Verification Checklist — Phase 2C
- Course list loads with paginated courses
- Search filter works (debounced, resets pagination)
- Status and category filters work
- Pagination works (previous/next)
- Clicking a course navigates to detail page
- Course detail shows metadata, lessons, quizzes
- Publish/Archive/New Version buttons appear per status
- Action buttons call correct APIs and refresh
- Loading/error/empty states work
- "Create Course" button navigates to editor
Dependencies
Phase 2A (routing).
Phase 2D: Course Editor — Create/Edit Wizard
Goal: Multi-step wizard for creating and editing courses, adding lessons, creating quizzes.
Files to Create
1. src/pages/safepath/courses/components/StepIndicator.tsx (NEW)
Step progress indicator: numbered circles connected by lines. States: completed (green check), current (coral filled), upcoming (gray outlined).
2. src/pages/safepath/courses/components/CourseDetailsForm.tsx (NEW)
Step 1 form. Fields for CourseCreatePayload: title (required), description, category (dropdown from getCategories()), OSHA standard ref, estimated duration, passing score percent, max retakes, locale. Controlled form state with validation.
3. src/pages/safepath/courses/components/LessonEditor.tsx (NEW)
Step 2 form:
- List of existing lessons with up/down arrows for sort order
- "Add Lesson" opens inline form: title, lesson_type dropdown, content, sort_order, completion_threshold_percent
- Edit/Delete per lesson
- Calls
addLesson(),updateLesson(),deleteLesson()APIs
4. src/pages/safepath/courses/components/QuizEditor.tsx (NEW)
Step 3 form:
- "Add Quiz" button →
addQuiz()API - Per quiz: title, list of questions
- "Add Question" opens inline form: question_type dropdown, question_text, dynamic options list (add/remove with is_correct checkbox), explanation
- Edit/Delete per question
- Calls
addQuestion(),updateQuestion(),deleteQuestion()APIs
5. src/pages/safepath/courses/components/CourseReviewStep.tsx (NEW)
Step 4: Read-only summary. Shows all course data, lessons, quizzes. Validation warnings (e.g., "No lessons added", "Quiz has no questions").
6. src/pages/safepath/courses/components/CourseEditorWizard.tsx (NEW)
Container component orchestrating steps 1–4 with <StepIndicator>. Manages:
- Step navigation (Back/Next)
- "Save Draft" and "Publish" buttons
- Create mode: Step 1 calls
createCourse()to getcourseId, then steps 2–3 use it - Edit mode: Step 1 calls
updateCourse(), steps 2–3 use existingcourseId
Files to Modify
7. src/pages/safepath/courses/CourseEditorPage.tsx (REPLACE skeleton)
- Checks URL params:
courseIdpresent → edit mode (loads existing course), absent → create mode - Renders
<CourseEditorWizard>with initial data if editing
Verification Checklist — Phase 2D
- "Create Course" navigates to
/safepath/courses/new - Step indicator shows all steps, highlights current
- Course details form validates required fields
- Category dropdown populated from API
- After step 1 "Next", course created via
createCourse()API - Lesson editor: add, edit, delete, reorder works
- Quiz editor: add quiz, add/edit/delete questions works
- Question options: add/remove options, toggle is_correct
- Review step shows complete summary
- "Save Draft" and "Publish" buttons work
- Edit mode loads existing course data into wizard
- Step navigation preserves data
- Toast notifications on success/error
Dependencies
Phase 2C (course list for navigation context).
Phase 2E: Training Matrix & Reports
Goal: Build the training matrix grid view and the three report pages with export functionality.
Files to Create
1. src/pages/safepath/matrix/components/MatrixGrid.tsx (NEW)
Employee-by-course compliance matrix using getTrainingMatrix() API.
Features:
- Column Headers: Course titles from
MatrixCourseHeader[]— rotated for compact display, tooltip with category/OSHA ref - Row Headers: Employee names from
MatrixEmployeeRow[]with email, site, role - Cells: Color-coded by
MatrixCellStatus.status:required→ bluein_progress→ ambercompleted→ greenoverdue→ redexpired→ graynot_assigned→ empty/dash
- Filters: Site, role, course, category dropdowns + status filter
- Summary: Overall compliance percentage
- Export: Button using
getTrainingMatrixExportUrl()→ opens download - Layout: Horizontal scroll with sticky first column (employee name)
2. src/pages/safepath/matrix/components/MatrixCellTooltip.tsx (NEW)
Tooltip on cell hover showing: assignment_id, due_date, completion_date, score_percent.
3. src/pages/safepath/reports/components/CompletionReportTab.tsx (NEW)
Completion report using getCompletionReport() API.
- Filters: Site, course, status, date range (date_from/date_to)
- Summary Cards: Counts from
AssignmentStatusCounts - Table:
CompletionReportRow[]— employee, course, dates, status, score, passed, delivery method, instructor - Export: CSV/PDF/XLSX buttons via
getCompletionReportExportUrl()
4. src/pages/safepath/reports/components/TranscriptTab.tsx (NEW)
Individual transcript using getIndividualTranscript() API.
- Employee Selector: Dropdown/search to pick a user
- Header: Employee name, email, company, generated date
- Stats: total_completed, total_in_progress, total_hours, certifications_active/expiring
- Table:
IndividualTranscriptRow[]— course, category, dates, scores, certificate info - Export: CSV/PDF via
getTranscriptExportUrl()
5. src/pages/safepath/reports/components/CertificationReportTab.tsx (NEW)
Certification status report using getCertificationReport() API.
- Filters: Site, status (active/expiring/expired)
- Summary: total_active, total_expiring_soon, total_expired
- Table:
CertificationStatusRow[]— employee, cert type, OSHA ref, dates, status, days until expiry, source - Export: CSV/PDF via
getCertificationReportExportUrl()
6. src/pages/safepath/reports/components/ReportExportButton.tsx (NEW)
Reusable export button with format dropdown. Constructs download URL and opens in new tab.
Files to Modify
7. src/pages/safepath/matrix/index.tsx (REPLACE skeleton)
Gradient header, filter bar, renders <MatrixGrid>.
8. src/pages/safepath/reports/index.tsx (REPLACE skeleton)
Tab navigation with 3 tabs: "Completion Report", "Individual Transcript", "Certification Status". Default: Completion Report.
Verification Checklist — Phase 2E
- Matrix loads and displays employee × course grid
- Matrix cells color-coded by status
- Matrix filters work (site, role, course, category)
- Matrix horizontal scroll with sticky first column
- Matrix export downloads file
- Completion report loads with filters and table
- Transcript loads for selected employee
- Certification report loads with filters
- All export buttons generate correct URLs
- Report tabs switch correctly
- Loading/error/empty states work
Dependencies
Phase 2A (routing).
Phase 2F: Assignments & Certifications
Goal: Build assignment management (list, create, bulk assign) and certification tracking (list, create, track expirations).
Types to Add
Add to src/types/safepath.ts:
// Assignment CRUD types
export interface AssignmentListItem {
assignment_id: string;
user_id: string;
employee_name: string;
employee_email: string;
course_id: string;
course_title: string;
assigned_by: string;
assigned_date: string;
due_date: string;
priority: string;
status: string;
progress_percent: number;
delivery_method: string;
score_percent: number | null;
completed_at: string | null;
}
export interface AssignmentListResponse {
items: AssignmentListItem[];
total: number;
page: number;
page_size: number;
}
export interface AssignmentCreatePayload {
user_id: string;
course_id: string;
due_date: string;
priority?: string;
delivery_method?: string;
}
export interface BulkAssignPayload {
user_ids: string[];
course_id: string;
due_date: string;
priority?: string;
}
// Certification CRUD types
export interface CertificationType {
certification_type_id: string;
name: string;
osha_standard_ref: string | null;
validity_months: number | null;
is_system: boolean;
}
export interface CertificationItem {
certification_id: string;
user_id: string;
employee_name: string;
employee_email: string;
certification_type_name: string;
issue_date: string;
expiration_date: string | null;
status: string;
source: string;
certificate_number: string | null;
}
export interface CertificationCreatePayload {
user_id: string;
certification_type_id: string;
issue_date: string;
expiration_date?: string;
certificate_number?: string;
source?: string;
}
API Functions to Add
Add to src/services/api/safepath.api.ts:
// Assignments
getAssignments(token, userId, companyId, params?)
getAssignment(token, userId, companyId, assignmentId)
createAssignment(token, userId, companyId, data)
bulkCreateAssignments(token, userId, companyId, data)
updateAssignment(token, userId, companyId, assignmentId, data)
startAssignment(token, userId, companyId, assignmentId)
submitAssignmentResult(token, userId, companyId, assignmentId, data)
// Auto-Assignment Rules
getAutoAssignRules(token, userId, companyId)
createAutoAssignRule(token, userId, companyId, data)
updateAutoAssignRule(token, userId, companyId, ruleId, data)
deleteAutoAssignRule(token, userId, companyId, ruleId)
// Classroom Sessions
createClassroomSession(token, userId, companyId, data)
updateClassroomSession(token, userId, companyId, sessionId, data)
// Certification Types
getCertificationTypes(token, userId, companyId)
createCertificationType(token, userId, companyId, data)
// Certifications CRUD
getCertifications(token, userId, companyId, params?)
createCertification(token, userId, companyId, data)
updateCertification(token, userId, companyId, certId, data)
deleteCertification(token, userId, companyId, certId)
Also update src/services/api/index.ts to import and re-export these functions.
Files to Create
1. src/pages/safepath/assignments/components/AssignmentList.tsx (NEW)
Assignment list using getAssignments():
- Filters: Status, course, employee search, date range
- Table: Rows with employee, course, dates, priority badge, status badge, progress bar
- Actions: "Create Assignment" and "Bulk Assign" buttons
2. src/pages/safepath/assignments/components/CreateAssignmentModal.tsx (NEW)
Modal form: employee selector, course selector (published courses), due date, priority, delivery method. Submit → createAssignment().
3. src/pages/safepath/assignments/components/BulkAssignModal.tsx (NEW)
Modal: multi-select employee list, course selector, due date, priority. Submit → bulkCreateAssignments().
4. src/pages/safepath/certifications/components/CertificationList.tsx (NEW)
Certification list using getCertifications():
- Filters: Status (active/expiring/expired), cert type, employee search
- Table: Employee, type, dates, status badge, days-until-expiry
- Color coding: Active (green), expiring (amber), expired (red)
- Actions: "Add Certification" button
5. src/pages/safepath/certifications/components/AddCertificationModal.tsx (NEW)
Modal: employee selector, cert type selector (from getCertificationTypes()), issue date, expiration date, certificate number, source. Submit → createCertification().
6. src/pages/safepath/certifications/components/CertificationTypesPanel.tsx (NEW)
Collapsible panel showing certification types with "Add Type" button → createCertificationType().
Files to Modify
7. src/pages/safepath/assignments/index.tsx (REPLACE skeleton)
Header + <AssignmentList> with create/bulk modals.
8. src/pages/safepath/certifications/index.tsx (REPLACE skeleton)
Header + tabs: "Certifications" and "Certification Types". Each renders its component.
9. src/types/safepath.ts — Add types listed above.
10. src/services/api/safepath.api.ts — Add API functions listed above.
11. src/services/api/index.ts — Re-export new functions.
Verification Checklist — Phase 2F
- Assignment list loads with filters and pagination
- Create Assignment modal validates and submits
- Bulk Assign modal allows multi-select and creates
- Assignment status badges display correctly
- Certification list loads with filters
- Add Certification modal creates successfully
- Certification types panel shows types
- Expiring/expired certifications highlighted
- Toast notifications on all CRUD operations
- Loading/error/empty states work
Dependencies
Phase 2A (routing). Phase 2C helps (course dropdowns for assignment creation).
Phase 2G: Quickstart Wizard
Goal: Post-onboarding quickstart wizard helping new administrators set up their training program with starter templates.
Files to Create
1. src/pages/safepath/quickstart/components/QuickstartChecklist.tsx (NEW)
Checklist using getQuickstartChecklist() API:
- Progress bar:
completion_percentandestimated_minutes_remaining - Ordered
QuickstartStep[]items: checkbox (completed=checked, disabled), title, description, "Optional" badge, action button linking toaction_url - Animated check marks for completed steps
2. src/pages/safepath/quickstart/components/StarterTemplatesPanel.tsx (NEW)
Template selection using getStarterTemplates() API:
- Grid of
StarterTemplateItem[]cards: title, description, category, OSHA ref, duration, lesson count, has_quiz badge, selectable checkbox - "Import Selected" button →
seedStarterTemplates()with selected template IDs - Success message with courses created count
3. src/pages/safepath/quickstart/components/QuickstartStatusBanner.tsx (NEW)
Dashboard banner using getQuickstartStatus():
- If complete: hidden or "Setup Complete" badge
- If incomplete: remaining steps count, "Continue Setup" button →
/safepath/quickstart
Files to Modify
4. src/pages/safepath/quickstart/index.tsx (REPLACE skeleton)
- Coral gradient header with rocket icon
- Two-column: checklist (left) + templates (right)
- If complete: congratulations message + link to dashboard
- If incomplete: checklist + templates
5. src/pages/safepath/dashboard/index.tsx (ADD banner)
Add <QuickstartStatusBanner> at top of dashboard when quickstart is incomplete.
Verification Checklist — Phase 2G
- Quickstart page loads with checklist and templates
- Checklist shows correct completion per step
- Progress bar accurate
- Action buttons navigate to correct pages
- Templates grid loads and displays cards
- Selecting and importing creates courses
- Success toast with course count
- Courses page shows newly imported courses
- Dashboard banner shows when incomplete
- Banner hides when complete
Dependencies
Phase 2A (routing), Phase 2B (dashboard for banner), Phase 2C (courses page for verification).
Phase 2H: Polish, Cross-Linking & Integration
Goal: Final phase — connect pages with cross-navigation links, add reusable header component, ensure consistent UX.
Files to Create
1. src/pages/safepath/components/SafePathPageHeader.tsx (NEW)
Standardized header with coral gradient, icon, title, subtitle, optional action buttons. Replaces repeated inline gradient headers across all pages.
Files to Modify
2. All SafePath page files
- Replace inline gradient headers with
<SafePathPageHeader> - Add cross-navigation links:
- Dashboard stat cards → relevant pages (overdue → assignments, certs → certifications)
- Course detail "Assign" button → assignment creation with course pre-selected
- Assignment rows → course detail
- Report employee names → individual transcript
- Matrix cells → assignment detail
- Team compliance rows → transcript
- Add "quick action" cards on dashboard: Create Course, Assign Training, View Reports, View Matrix
Verification Checklist — Phase 2H
- Consistent header styling across all pages
- All cross-navigation links work
- Dashboard quick actions navigate correctly
- Responsive design works on tablet/mobile
- Back buttons work on detail pages
- No dead links or broken navigation
- Consistent loading/error/empty patterns
Dependencies
All previous phases (2A–2G).
Complete File Inventory
New Files (~40 total)
| # | File | Phase |
|---|---|---|
| 1 | src/components/sidebar/SidebarSafePath.tsx | 2A |
| 2 | src/pages/safepath/dashboard/index.tsx | 2A→2B |
| 3 | src/pages/safepath/courses/index.tsx | 2A→2C |
| 4 | src/pages/safepath/courses/CourseDetailPage.tsx | 2A→2C |
| 5 | src/pages/safepath/courses/CourseEditorPage.tsx | 2A→2D |
| 6 | src/pages/safepath/assignments/index.tsx | 2A→2F |
| 7 | src/pages/safepath/certifications/index.tsx | 2A→2F |
| 8 | src/pages/safepath/matrix/index.tsx | 2A→2E |
| 9 | src/pages/safepath/reports/index.tsx | 2A→2E |
| 10 | src/pages/safepath/quickstart/index.tsx | 2A→2G |
| 11 | src/pages/safepath/dashboard/components/StatCard.tsx | 2B |
| 12 | src/pages/safepath/dashboard/components/EmployeeDashboard.tsx | 2B |
| 13 | src/pages/safepath/dashboard/components/AdminDashboard.tsx | 2B |
| 14 | src/pages/safepath/courses/components/CourseStatusBadge.tsx | 2C |
| 15 | src/pages/safepath/courses/components/CourseListTable.tsx | 2C |
| 16 | src/pages/safepath/courses/components/LessonCard.tsx | 2C |
| 17 | src/pages/safepath/courses/components/QuizCard.tsx | 2C |
| 18 | src/pages/safepath/courses/components/StepIndicator.tsx | 2D |
| 19 | src/pages/safepath/courses/components/CourseDetailsForm.tsx | 2D |
| 20 | src/pages/safepath/courses/components/LessonEditor.tsx | 2D |
| 21 | src/pages/safepath/courses/components/QuizEditor.tsx | 2D |
| 22 | src/pages/safepath/courses/components/CourseReviewStep.tsx | 2D |
| 23 | src/pages/safepath/courses/components/CourseEditorWizard.tsx | 2D |
| 24 | src/pages/safepath/matrix/components/MatrixGrid.tsx | 2E |
| 25 | src/pages/safepath/matrix/components/MatrixCellTooltip.tsx | 2E |
| 26 | src/pages/safepath/reports/components/CompletionReportTab.tsx | 2E |
| 27 | src/pages/safepath/reports/components/TranscriptTab.tsx | 2E |
| 28 | src/pages/safepath/reports/components/CertificationReportTab.tsx | 2E |
| 29 | src/pages/safepath/reports/components/ReportExportButton.tsx | 2E |
| 30 | src/pages/safepath/assignments/components/AssignmentList.tsx | 2F |
| 31 | src/pages/safepath/assignments/components/CreateAssignmentModal.tsx | 2F |
| 32 | src/pages/safepath/assignments/components/BulkAssignModal.tsx | 2F |
| 33 | src/pages/safepath/certifications/components/CertificationList.tsx | 2F |
| 34 | src/pages/safepath/certifications/components/AddCertificationModal.tsx | 2F |
| 35 | src/pages/safepath/certifications/components/CertificationTypesPanel.tsx | 2F |
| 36 | src/pages/safepath/quickstart/components/QuickstartChecklist.tsx | 2G |
| 37 | src/pages/safepath/quickstart/components/StarterTemplatesPanel.tsx | 2G |
| 38 | src/pages/safepath/quickstart/components/QuickstartStatusBanner.tsx | 2G |
| 39 | src/pages/safepath/components/SafePathPageHeader.tsx | 2H |
Modified Files
| File | Phases |
|---|---|
src/App.tsx | 2A |
src/components/Sidebar.tsx | 2A |
src/types/safepath.ts | 2F |
src/services/api/safepath.api.ts | 2F |
src/services/api/index.ts | 2F |