npm package: @schoolio/player
Description: Quiz Player component for loading and playing quizzes, and attempts from Quiz Engine. Now with AI Helper!
Latest version: 1.5.2

# @schoolio/player

React components for loading quizzes and displaying attempt results from Quiz Engine.

## Components

- **QuizPlayer** - Interactive quiz-taking component
- **AttemptViewer** - Displays quiz attempt results with detailed breakdown

## Installation

```bash
npm install @schoolio/player
```

## Usage

```tsx
import { QuizPlayer } from '@schoolio/player';

function MyQuizPage() {
  return (
    <QuizPlayer
      quizId="QZ123"
      lessonId="L12"
      assignLessonId="assignLesson123"
      courseId="course456"
      childId="child789"
      parentId="parent012"
      apiBaseUrl="https://your-quiz-engine-url.com"
      onComplete={(result) => {
        console.log('Quiz completed!', result);
        // result contains: attemptId, score, correctAnswers, totalQuestions, answers, timeSpentSeconds
      }}
      onError={(error) => {
        console.error('Quiz error:', error);
      }}
      onProgress={(progress) => {
        console.log(`Question ${progress.currentQuestion} of ${progress.totalQuestions}`);
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `quizId` | string | Yes | The ID of the quiz to load |
| `lessonId` | string | Yes | Lesson ID from your app |
| `assignLessonId` | string | Yes | Assigned lesson ID for tracking |
| `courseId` | string | Yes | Course ID for tracking |
| `childId` | string | Yes | Student/child ID |
| `parentId` | string | Yes | Parent ID |
| `apiBaseUrl` | string | Yes | Base URL of your Quiz Engine API |
| `authToken` | string | No | Optional auth token for API requests |
| `onComplete` | function | No | Callback when quiz is completed |
| `onError` | function | No | Callback when an error occurs |
| `onProgress` | function | No | Callback on question navigation |
| `className` | string | No | CSS class for the container |

## Quiz Result

When the quiz is completed, the `onComplete` callback receives:

```typescript
interface QuizResult {
  attemptId: string;          // Unique attempt ID
  score: number;              // Percentage score (0-100)
  correctAnswers: number;     // Number of correct answers
  totalQuestions: number;     // Total questions in quiz
  answers: QuizAnswerDetail[]; // Detailed answer data
  timeSpentSeconds: number;   // Time taken to complete
}
```

## Attempt Tracking

The component automatically:
- Creates a new attempt when started
- Saves progress as the student answers questions
- Resumes from where the student left off if they return
- Tracks attempt number (1st, 2nd, 3rd attempt, etc.)
- Records time spent on the quiz

## API Endpoints

The component expects these endpoints on your Quiz Engine:

- `GET /api/external/quizzes/:id` - Get quiz by ID
- `POST /api/external/quiz-attempts` - Create new attempt
- `PATCH /api/external/quiz-attempts/:id` - Update attempt
- `GET /api/external/quiz-attempts/:id` - Get attempt by ID
- `GET /api/external/quiz-attempts?assignLessonId=X&childId=Y` - Get attempts

## Customization

You can provide custom styling via the `className` prop and CSS:

```css
.my-quiz-player {
  /* Custom container styles */
}

.my-quiz-player .quiz-question {
  /* Custom question styles */
}
```

## Using the API Client Directly

For more control, you can use the API client directly:

```typescript
import { QuizApiClient } from '@schoolio/player';

const client = new QuizApiClient({
  baseUrl: 'https://your-quiz-engine-url.com',
  authToken: 'optional-auth-token',
});

// Fetch a quiz
const quiz = await client.getQuiz('quiz-id');

// Create an attempt
const attempt = await client.createAttempt({
  quizId: 'quiz-id',
  lessonId: 'lesson-id',
  assignLessonId: 'assign-lesson-id',
  courseId: 'course-id',
  childId: 'child-id',
  parentId: 'parent-id',
});

// Update attempt with answers
await client.updateAttempt(attempt.id, {
  answers: [...],
  status: 'completed',
  score: 80,
  correctAnswers: 8,
  timeSpentSeconds: 300,
});
```

---

## AttemptViewer

The `AttemptViewer` component displays quiz attempt results with a summary and detailed question-by-question breakdown.

### Usage

```tsx
import { AttemptViewer } from '@schoolio/player';

function MyResultsPage() {
  return (
    <AttemptViewer
      attemptId={123}
      apiBaseUrl="https://your-quiz-engine-url.com"
    />
  );
}
```

### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `attemptId` | `number` | Yes | The ID of the quiz attempt to display |
| `apiBaseUrl` | `string` | Yes | Base URL of your Quiz Engine API |
| `title` | `string` | No | Optional title (reserved for future use) |

### API Endpoint Required

The component expects this endpoint:

```
GET {apiBaseUrl}/api/quiz-attempts/{attemptId}/results
```

**Response format:**

```json
{
  "attempt": {
    "id": 123,
    "quizId": 1,
    "score": 80,
    "totalQuestions": 10,
    "correctAnswers": 8,
    "timeTaken": 300,
    "completedAt": "2025-01-02T10:00:00Z",
    "answers": { "1": "selected_answer", "2": "another_answer" }
  },
  "questions": [
    {
      "id": 1,
      "questionText": "What is 2+2?",
      "questionType": "multiple_choice",
      "options": ["3", "4", "5"],
      "correctAnswer": "4",
      "explanation": "Basic addition"
    }
  ]
}
```

### Styling

The component uses 100% width to fill its parent container. Wrap it in a sized container to control dimensions:

```tsx
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
  <AttemptViewer attemptId={123} apiBaseUrl="https://api.example.com" />
</div>
```

### Features

- **Summary cards** showing score, questions count, and time taken
- **Detailed breakdown** of each question with correct/incorrect indicators
- **Explanations** displayed for each question when available
- **Purple theme** (#6721b0) matching the QuizPlayer design
- **Responsive layout** that adapts to container width

---

## License

MIT