npm package: @mailmarc/react-course-viewer
Description: A powerful React component for creating interactive learning courses with markdown support
Author: Sheridan Computers Limited
Latest version: 1.0.1

# @mailmarc/react-course-viewer

[![Test](https://github.com/MailMARC/react-course-viewer/actions/workflows/test.yml/badge.svg)](https://github.com/MailMARC/react-course-viewer/actions/workflows/test.yml)
[![NPM Version](https://img.shields.io/npm/v/@mailmarc/react-course-viewer.svg)](https://www.npmjs.com/package/@mailmarc/react-course-viewer)
[![NPM Downloads](https://img.shields.io/npm/dm/@mailmarc/react-course-viewer.svg)](https://www.npmjs.com/package/@mailmarc/react-course-viewer)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/MailMARC/react-course-viewer/blob/main/LICENSE)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
[![React](https://img.shields.io/badge/React-18%20%7C%2019-61dafb.svg)](https://reactjs.org/)

A powerful React component library for creating interactive learning courses with markdown content. Build engaging educational experiences with section-based navigation, progress tracking, achievements, and celebration effects.

## Features

✅ **Section-based Navigation**: Proper course structure with sections and lessons  
✅ **Dynamic Content Loading**: Load markdown files from docs folders  
✅ **Progress Tracking**: Persistent progress with localStorage  
✅ **Achievement System**: Built-in achievements for course milestones  
✅ **Keyboard Navigation**: Arrow keys, Space, Enter support  
✅ **Touch Gestures**: Swipe navigation on mobile devices  
✅ **Theme Support**: Light/dark/system themes  
✅ **Responsive Design**: Works on desktop and mobile  
✅ **Accessibility**: WCAG compliant with focus management  
✅ **TypeScript**: Full type safety and IntelliSense  

## Installation

```bash
npm install @mailmarc/react-course-viewer
# or
yarn add @mailmarc/react-course-viewer
# or
pnpm add @mailmarc/react-course-viewer
```

## Quick Start

### 1. Basic Usage

```tsx
import { CourseViewer, CourseLoader } from '@mailmarc/react-course-viewer';

function MyTrainingPage() {
  const [course, setCourse] = useState(null);

  useEffect(() => {
    const loadCourse = async () => {
      const loader = new CourseLoader();
      const course = await loader.loadCourse(COURSE_CONFIGS.dmarc);
      setCourse(course);
    };
    loadCourse();
  }, []);

  if (!course) return <div>Loading...</div>;

  return (
    <CourseViewer
      course={course}
      onComplete={(cert) => handleCourseComplete(cert)}
      theme="light"
      autoAdvance={true}
    />
  );
}
```

### 2. With Loading States

```tsx
import { DMARCCourseExample } from '../components/ui/CourseViewer';

function LearningPage() {
  return <DMARCCourseExample />;
}
```

### 3. Custom Course

```tsx
const customCourse = {
  id: 'security-basics',
  title: 'Security Basics',
  description: 'Learn fundamental security concepts',
  version: '1.0.0',
  sections: [
    {
      id: 'intro',
      title: 'Introduction',
      slug: 'intro',
      order: 1,
      lessons: [
        {
          id: 'what-is-security',
          title: 'What is Security?',
          slug: 'what-is-security',
          content: '# What is Security?\n\nSecurity protects your data...',
          duration: 5,
          order: 1,
        },
      ],
    },
  ],
};

<CourseViewer course={customCourse} />
```

## CourseViewer Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `course` | `Course` | **required** | Course data structure |
| `onComplete` | `(cert: Certificate) => void` | - | Called when course is completed |
| `onProgress` | `(progress: CourseProgress) => void` | - | Called when progress updates |
| `theme` | `'light' \| 'dark' \| 'system'` | `'light'` | UI theme |
| `autoAdvance` | `boolean` | `true` | Auto-advance after lesson completion |
| `autoAdvanceDelay` | `number` | `2` | Seconds to wait before auto-advance |
| `enableKeyboardNavigation` | `boolean` | `true` | Enable keyboard shortcuts |
| `enableSwipeGestures` | `boolean` | `true` | Enable touch gestures |
| `enableSoundEffects` | `boolean` | `false` | Play sounds for achievements |
| `className` | `string` | `''` | Additional CSS classes |

## Course Data Structure

### Course Type

```typescript
interface Course {
  id: string;                    // Unique course identifier
  title: string;                 // Course display title
  description: string;           // Course description
  version: string;               // Course version
  sections: Section[];           // Course sections
  metadata?: {
    author: string;
    difficulty: 'beginner' | 'intermediate' | 'advanced';
    estimatedHours: number;
  };
}
```

### Section Type

```typescript
interface Section {
  id: string;                    // Unique section identifier
  title: string;                 // Section display title
  slug: string;                  // URL-friendly section name
  description?: string;          // Optional section description
  lessons: Lesson[];             // Lessons in this section
  order: number;                 // Display order
}
```

### Lesson Type

```typescript
interface Lesson {
  id: string;                    // Unique lesson identifier
  title: string;                 // Lesson display title
  slug: string;                  // URL-friendly lesson name
  content: string;               // Markdown content
  duration?: number;             // Estimated reading time (minutes)
  tags?: string[];               // Topic tags
  order: number;                 // Display order within section
  canMarkComplete?: boolean;     // Whether lesson can be marked complete
}
```

## CourseLoader

The `CourseLoader` class handles loading markdown files from the filesystem and converting them into course data.

### Configuration

```typescript
const courseConfig = {
  id: 'my-course',
  title: 'My Course',
  description: 'Learn amazing things',
  version: '1.0.0',
  docsPath: '/docs/learning-centre',  // Path to markdown files
  sectionsConfig: [
    {
      id: '01-introduction',
      title: 'Introduction',
      order: 1,
      lessons: [
        {
          id: '01-intro-basics',
          title: 'Basics',
          fileName: 'basics.md',           // Actual markdown file name
          duration: 5,
          order: 1,
        },
      ],
    },
  ],
};

const loader = new CourseLoader();
const course = await loader.loadCourse(courseConfig);
```

### Built-in Configurations

```typescript
import { COURSE_CONFIGS } from '../components/ui/CourseViewer';

// DMARC course with proper docs structure
const dmarcCourse = await loader.loadCourse(COURSE_CONFIGS.dmarc);
```

## Progress Tracking

Progress is automatically saved to `localStorage` and includes:

- Current section and lesson position
- Completed lessons list
- Time spent per lesson
- Earned achievements
- Course start and last access times

```typescript
// Access progress data
const progress = {
  courseId: 'dmarc-expert-course',
  currentSectionIndex: 2,
  currentLessonIndex: 1,
  completedLessons: ['lesson-1', 'lesson-2', 'lesson-3'],
  achievements: [{ id: 'first-step', name: 'First Step!', ... }],
  timeSpent: { 'lesson-1': 5, 'lesson-2': 3 },
  startedAt: new Date(),
  lastAccessed: new Date(),
};
```

## Navigation

### Keyboard Shortcuts

- `→` or `Space`: Next lesson (if current lesson is complete)
- `←`: Previous lesson
- `Enter`: Mark current lesson as complete
- `Esc`: Menu (future feature)

### Touch Gestures

- **Swipe Left**: Next lesson (if current lesson is complete)
- **Swipe Right**: Previous lesson

### Section-Based Navigation

Unlike the old flattened approach, the new CourseViewer shows:

```
Section 2: SPF (Safe Postman Friends) - Lesson 3 of 4
```

Instead of:
```
Lesson 7 of 15  ❌ (old flattened approach)
```

## Achievements

Built-in achievements are unlocked automatically:

- 👶 **First Step**: Complete your first lesson
- 📬 **Quarter Master**: 25% course completion  
- 🦸 **Halfway Hero**: 50% course completion
- 🚀 **Almost There**: 75% course completion
- 🎓 **Course Expert**: 100% course completion

## Theming

The component supports three themes:

```tsx
<CourseViewer theme="light" />   // Light mode
<CourseViewer theme="dark" />    // Dark mode  
<CourseViewer theme="system" />  // Follow system preference
```

CSS custom properties can be overridden:

```css
.course-viewer[data-theme="custom"] {
  --course-primary: #your-color;
  --course-background: #your-bg;
  /* etc. */
}
```

## Package Structure

```
@mailmarc/react-course-viewer/
├── dist/
│   ├── index.js           # CommonJS bundle
│   ├── index.esm.js       # ESM bundle
│   ├── package-index.d.ts # TypeScript definitions
│   └── styles.css         # Component styles
├── src/
│   ├── index.tsx          # Main CourseViewer component
├── types.ts               # TypeScript types
├── CourseLoader.ts        # Dynamic content loading
├── useProgress.ts         # Progress tracking hook
├── CourseViewer.css       # Component styles
├── examples.tsx           # Usage examples
└── README.md              # This documentation
```

## Markdown Content Setup

1. **Copy docs to public directory**:
   ```bash
   cd frontend/public && cp -r ../../docs/learning-centre docs/
   ```

2. **Or use the provided script**:
   ```bash
   cd frontend/public/docs && ./copy_docs.sh
   ```

3. **Docs structure should match config**:
   ```
   public/docs/learning-centre/
   ├── 01-introduction/
   │   ├── what-is-dmarc.md
   │   ├── why-email-authentication-matters.md
   │   └── dmarc-vs-spf-vs-dkim.md
   ├── 02-spf/
   │   └── spf-basics.md
   └── ...
   ```

## Migration from Old CourseViewer

The new CourseViewer fixes several issues from the old implementation:

### ✅ Fixed Issues

1. **Flattened Lessons**: Now shows proper section-based progress
2. **Static Content**: Now loads actual markdown files dynamically  
3. **Hard-coded Course**: Now supports any course configuration
4. **Poor Progress Display**: Now shows "Section X - Lesson Y of Z"

### 🔄 Migration Steps

1. **Replace import**:
   ```tsx
   // Old
   import CourseViewer from '../components/CourseViewer';
   
   // New  
   import { CourseViewer } from '../components/ui/CourseViewer';
   ```

2. **Update usage**:
   ```tsx
   // Old (static course)
   <CourseViewer course={LOADED_DMARC_COURSE} />
   
   // New (dynamic loading)
   const [course, setCourse] = useState(null);
   useEffect(() => {
     const loadCourse = async () => {
       const loader = new CourseLoader();
       const course = await loader.loadCourse(COURSE_CONFIGS.dmarc);
       setCourse(course);
     };
     loadCourse();
   }, []);
   ```

3. **Add loading states**:
   ```tsx
   if (!course) return <div>Loading course...</div>;
   ```

## Browser Compatibility

- ✅ Chrome 90+
- ✅ Firefox 88+  
- ✅ Safari 14+
- ✅ Edge 90+
- ✅ Mobile browsers

## Accessibility Features

- ✅ Keyboard navigation
- ✅ Focus management  
- ✅ ARIA labels
- ✅ Screen reader support
- ✅ High contrast themes
- ✅ Reduced motion support

## Performance

- **Bundle size**: ~50KB gzipped (component only, excludes peer dependencies)
- **Rendering**: Optimized with React.memo and useMemo
- **Content loading**: Lazy loading of markdown files
- **Progress tracking**: Debounced localStorage updates

## Contributing

To add a new course:

1. Create markdown files in your project's `public/docs/` folder structure
2. Use `MarkdownCourseLoader` to load markdown-based courses
3. Or use `CourseLoader` for programmatic course creation
4. Extend the `Course`, `Section`, or `Lesson` interfaces for custom features

## License

MIT © 2025 Sheridan Computers Limited