# Tutorial System

## Overview

The tutorial system provides guided walkthroughs for users. Tutorials are defined as JSON files, processed server-side by PHP (translations, conditions, user variables), and rendered client-side by the TutorialEngine.

## Architecture

```
resources/tutorials/dashboard-view.json     ← You author this (pure data)
         ↓
PHP: TutorialProcessor                      ← Translates, filters, replaces variables
         ↓
GET /api/tutorials/dashboard-view           ← Serves processed JSON
         ↓
JS: TutorialEngine                          ← Renders overlay, bubble, cursor, highlights
```

### Key components

| Component | Role |
|-----------|------|
| **TutorialEngine** (JS) | Orchestrates modules: Overlay, Bubble, Cursor, Highlight, etc. |
| **TutorialProcessor** (PHP) | Loads JSON, translates strings, evaluates conditions, replaces `{{variables}}` |
| **TutorialConditionEvaluator** (PHP) | Safe expression parser for `showIf` conditions |
| **HasTutorial** (PHP plugin) | Auto-detects tutorials for Kompo components, triggers on first visit |
| **TutorialStepBuilder** (PHP + JS) | Dev-only visual editor for editing steps live |

## Creating a Tutorial

### 1. Create the JSON file

Place it in `resources/tutorials/{component-slug}.json`. The slug matches the Kompo component name (e.g., `DashboardView` → `dashboard-view`).

```json
{
    "steps": [
        {
            "html": "tutorial.welcome"
        },
        {
            "html": "tutorial.click-here",
            "highlight": { "groups": [{ "elements": ["#my-button"] }] },
            "position": "right"
        },
        {
            "html": "tutorial.fill-form",
            "highlight": { "groups": [{ "elements": [".form-field", ".submit-btn"] }] },
            "cursor": {
                "from": ".form-field",
                "to": ".submit-btn",
                "click": true,
                "duration": 1.5
            }
        }
    ]
}
```

### 2. Add translations

In your translation files (`resources/lang/en/tutorial.php`):

```php
return [
    'welcome' => 'Welcome, {{user_first_name}}! Let me show you around.',
    'click-here' => 'Click this button to get started.',
    'fill-form' => 'Fill in the form and hit submit.',
];
```

The PHP processor translates keys and replaces `{{user_first_name}}`, `{{user_last_name}}`, `{{user_name}}` automatically.

### 3. That's it

The `HasTutorial` plugin auto-detects the JSON file based on the component slug and starts the tutorial on first visit. A replay button in the navbar lets users re-watch it anytime.

## Step Configuration

Each step supports these properties:

```json
{
    "html": "translation.key",

    "position": "left | right | top | bottom",
    "align": "left | center | right",
    "overlay": true,

    "highlight": {
        "groups": [{ "elements": [".selector1", ".selector2"] }],
        "padding": 8,
        "borderRadius": 8
    },

    "cursor": {
        "from": ".start-element",
        "to": ".end-element",
        "click": true,
        "duration": 1.5,
        "loop": true
    },

    "hover": ".element-to-force-hover",

    "scrollTo": ".element-to-scroll-into-view",
    "scrollInside": { "selector": ".container", "by": 200, "duration": 1 },

    "options": [
        { "label": "tutorial.option-a", "goToStep": 4 },
        { "label": "tutorial.option-b", "done": true },
        { "label": "tutorial.option-c", "redirect": "/other-page" }
    ],

    "autoNext": 3,
    "advance": "click | afterAnimation",
    "silentClick": ".element-to-auto-click",
    "showBack": true,
    "chatMode": true,

    "showIf": "permission:ManageTeam && !setting:hide_tutorial",

    "redirect": "/next-page"
}
```

## Triggering Tutorials

### Automatic (first visit)

The `HasTutorial` plugin handles this. If `resources/tutorials/{component-slug}.json` exists, the tutorial starts on first visit and is marked as viewed.

### Button click (replay)

```php
// Uses 'default' — auto-resolves to current page's tutorial
_Button('Help')->initTutorial();

// Or specify a tutorial explicitly
_Button('Start Tour')->initTutorial('campaign-settings');

// Start at a specific step
_Button('Show Step 3')->initTutorial('campaign-settings', stepNumber: 2);
```

### On page load (cross-page redirect)

Use `_Tutorial()` in a component's `render()` method:

```php
function render()
{
    return _Rows(
        _Tutorial('onboarding-step-2'),
        // ... rest of component
    );
}
```

This supports cross-page chaining — when a tutorial redirects to another page with `?tutorial=name&fromStep=N`, the `_Tutorial()` helper picks it up and starts automatically.

## Conditional Steps

Use `showIf` to conditionally show steps based on user permissions, settings, or DOM elements:

```json
{ "showIf": "permission:ManageTeam" }
{ "showIf": "permission:EditCampaign && !setting:onboarding_done" }
{ "showIf": "(role:admin || role:manager) && permission:ViewFinances" }
{ "showIf": "selector:.optional-feature-panel" }
```

**Built-in condition types:**
- `permission:X` — checks `user->hasPermission(X)`
- `setting:X` — checks `user->getSettingValue(X)`
- `role:X` — checks `user->hasRole(X)`
- `selector:X` — checks if DOM element exists (evaluated client-side)

**Custom conditions** — register in a service provider:

```php
TutorialConditionEvaluator::register('hasActiveSubscription',
    fn() => auth()->user()->subscription?->isActive() ?? false
);
```

Then use: `"showIf": "hasActiveSubscription && permission:ManageBilling"`

## Cross-Page Tutorials

When a step needs to redirect to another page and continue:

```json
{
    "html": "tutorial.go-to-settings",
    "options": [
        {
            "label": "tutorial.lets-go",
            "redirect": "/campaign/settings",
            "startTutorial": "campaign-settings"
        }
    ]
}
```

The target page should have `_Tutorial('campaign-settings')` in its render method to pick up the redirect.

## Dev Mode: Step Builder

In debug mode (`APP_DEBUG=true`):
- A step builder panel is available in the navbar
- Clicking the replay button also opens the visual editor
- Edit step properties, pick elements, preview live changes
- Copy the JSON output to update your tutorial file

## File Structure

```
js-kompo-utils/tutorials/
├── TutorialEngine.js          # Main orchestrator
├── TutorialConfig.js          # Defaults + config
├── tutorial.scss              # All tutorial styles
├── modules/
│   ├── Avatar.js              # Container + avatar image
│   ├── Overlay.js             # Full-screen overlay
│   ├── Bubble.js              # Speech bubble + positioning
│   ├── Typewriter.js          # Character-by-character text
│   ├── Cursor.js              # Animated cursor + click pulse
│   ├── Highlight.js           # SVG cutout overlay
│   ├── HoverForcer.js         # Force :hover styles
│   ├── Scroll.js              # Scroll helpers
│   ├── Options.js             # Choice buttons
│   ├── AutoNext.js            # Timed progress bar
│   └── Mobile.js              # Mobile detection + tab handling
├── utils/
│   ├── selectors.js           # CSS selector utilities
│   ├── svg.js                 # SVG element helpers
│   └── stability.js           # Element position polling
└── step-builder/              # Dev-only visual editor
    ├── step-builder-bridge.js
    └── utils/

utils/src/Tutorials/
├── TutorialProcessor.php      # JSON loading + translation + conditions
├── TutorialConditionEvaluator.php  # Safe expression parser
└── TutorialStepBuilder.php    # Kompo Form for visual editor
```
