npm package: @patch-adams/plugin-feedback
Description: Feedback widget plugin for Patch-Adams - inject a feedback form into Rise courses
Latest version: 1.0.14

# @patch-adams/plugin-feedback

A feedback widget plugin for Patch-Adams that injects a customizable feedback form into Rise courses.

## Features

- Star rating (configurable 3-10 stars)
- Issue type dropdown with subtypes
- Comment field with character counter
- Auto-detects language from `<html lang>` or `<body lang>` attribute
- Live language switching (English/French)
- Submits to configurable endpoint
- Fully customizable appearance and behavior

## Installation

```bash
npm install @patch-adams/plugin-feedback
```

## Usage

Configure the feedback plugin in your patch configuration:

```typescript
import { patchCourse } from '@patch-adams/core';
import feedbackPlugin from '@patch-adams/plugin-feedback';

const result = await patchCourse(courseZip, {
  plugins: {
    feedback: {
      enabled: true,
      tabText: 'Feedback',
      tabColor: '#da291c',
      position: 'right',
      endpoint: 'https://api.example.com/feedback',
      showRating: true,
      showIssueType: true,
      showComment: true,
    },
  },
});
```

## Language Detection

The widget automatically detects the language from the HTML document:

1. Checks `<html lang="xx">` attribute
2. Falls back to `<body lang="xx">` attribute
3. Falls back to `config.locale` value
4. Defaults to English

Language variants are normalized: `fr-CA` → `fr`, `en-US` → `en`

**Live switching**: If the `lang` attribute changes at runtime (e.g., via JavaScript or DevTools), the widget automatically re-renders with the new language.

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | boolean | `true` | Enable/disable the plugin |
| `endpoint` | string | - | URL to POST feedback data |
| `method` | `'POST'` \| `'PUT'` | `'POST'` | HTTP method |
| `headers` | object | - | Additional headers for the request |
| `position` | `'left'` \| `'right'` | `'right'` | Tab position |
| `tabText` | string | `'Feedback'` | Text on the tab button |
| `tabColor` | string | `'#da291c'` | Tab background color |
| `tabTextColor` | string | `'#ffffff'` | Tab text color |
| `zIndex` | number | `9999` | Widget z-index |
| `showRating` | boolean | `true` | Show star rating |
| `ratingRequired` | boolean | `false` | Require rating to submit |
| `ratingStars` | number | `5` | Number of stars (3-10) |
| `showIssueType` | boolean | `true` | Show issue type dropdown |
| `issueTypeRequired` | boolean | `false` | Require issue type |
| `issueTypes` | array | default types | Custom issue types |
| `showComment` | boolean | `true` | Show comment field |
| `commentRequired` | boolean | `false` | Require comment |
| `commentMaxLength` | number | `500` | Max comment length |
| `locale` | `'en'` \| `'fr'` | `'en'` | Default locale (auto-detected at runtime) |
| `translations` | object | - | Custom translation overrides |
| `autoClose` | boolean | `true` | Auto-close after success |
| `autoCloseDelay` | number | `2000` | Delay before auto-close (ms) |
| `debug` | boolean | `false` | Enable debug logging |
| `includeMetadata` | object | all true | What metadata to include |

## Custom Issue Types

```typescript
{
  issueTypes: [
    {
      id: 'content',
      label: 'Content Issue',
      subtypes: [
        { id: 'typo', label: 'Typo / Grammar' },
        { id: 'incorrect', label: 'Incorrect Information' },
      ],
    },
    {
      id: 'technical',
      label: 'Technical Issue',
    },
    {
      id: 'other',
      label: 'Other',
    },
  ],
}
```

## Metadata

By default, feedback submissions include:

- `courseId` - From `data-pa-course-id` attribute on `<html>`
- `courseTitle` - From LRS bridge if available
- `lessonId` - Current URL hash or pathname
- `userAgent` - Browser user agent
- `timestamp` - ISO 8601 timestamp
- `url` - Current page URL

## Submitted Data Format

```json
{
  "rating": 4,
  "issueType": "content",
  "issueSubtype": "typo",
  "comment": "Found a typo on slide 3",
  "metadata": {
    "courseId": "course-123",
    "courseTitle": "Safety Training",
    "lessonId": "#/lessons/intro",
    "userAgent": "Mozilla/5.0...",
    "timestamp": "2024-01-15T10:30:00.000Z",
    "url": "https://example.com/course/#/lessons/intro"
  }
}
```

## License

MIT