# Migration Guide

This guide helps migrate existing templates to use the new standardized UX patterns.

## Overview

The ThrillWiki UX standardization introduces:

1. **Breadcrumb system** with Schema.org support
2. **Skeleton screens** for loading states
3. **Standardized form validation** with HTMX
4. **Toast notifications** with action support
5. **Page headers** with consistent layout
6. **Action bars** for button placement
7. **Enhanced modals** with focus trapping
8. **HTMX response utilities** for views

## Step-by-Step Migration

### Step 1: Update Base Template Usage

Ensure your templates extend the base template correctly:

```django
{% extends 'base/base.html' %}

{% block title %}Your Page Title{% endblock %}

{% block content %}
    <!-- Your content -->
{% endblock %}
```

### Step 2: Add Breadcrumbs

#### In Your View

```python
from apps.core.utils import BreadcrumbBuilder

def your_view(request):
    request.breadcrumbs = (
        BreadcrumbBuilder()
        .add_home()
        .add('Section', '/section/')
        .add_current('Current Page')
        .build()
    )
    return render(request, 'your_template.html')
```

#### In Your Template

The breadcrumbs are automatically rendered if you're using the base template.
If you need to place them elsewhere:

```django
{% include 'components/navigation/breadcrumbs.html' %}
```

### Step 3: Replace Page Headers

#### Before

```html
<div class="page-header">
    <h1>Parks</h1>
    <a href="/parks/create/" class="btn">Add Park</a>
</div>
```

#### After

```django
{% include 'components/layout/page_header.html' with
    title='Parks'
    subtitle='Browse theme parks worldwide'
    primary_action_url='/parks/create/'
    primary_action_text='Add Park'
    primary_action_icon='fas fa-plus'
%}
```

### Step 4: Update Form Fields

#### Before

```html
<div class="form-group">
    <label for="name">Name</label>
    {{ form.name }}
    {% if form.name.errors %}
        <span class="error">{{ form.name.errors.0 }}</span>
    {% endif %}
</div>
```

#### After

```django
{% include 'forms/partials/form_field.html' with field=form.name %}
```

For multiple fields with consistent styling:

```django
{% for field in form %}
    {% include 'forms/partials/form_field.html' with field=field %}
{% endfor %}
```

### Step 5: Update Form Actions

#### Before

```html
<div class="form-buttons">
    <a href="/cancel/">Cancel</a>
    <button type="submit">Save</button>
</div>
```

#### After

```django
{% include 'forms/partials/form_actions.html' with
    submit_text='Save Park'
    cancel_url='/parks/'
%}
```

Or use the action bar for more options:

```django
{% include 'components/ui/action_bar.html' with
    align='between'
    primary_action_text='Save'
    tertiary_action_text='Cancel'
    tertiary_action_url='/parks/'
%}
```

### Step 6: Add Loading States

#### For Page Sections

```django
<div id="parks-list"
     hx-get="{% url 'parks:list' %}"
     hx-trigger="load"
     hx-swap="innerHTML">
    {% include 'components/skeletons/card_grid_skeleton.html' with cards=6 %}
</div>
```

#### For Forms

```django
<form hx-post="{% url 'parks:create' %}"
      hx-target="#form-container"
      hx-indicator="#form-loading">
    {% csrf_token %}
    <!-- Form fields -->

    <div id="form-loading" class="htmx-indicator">
        {% include 'htmx/components/loading_indicator.html' with text='Saving...' %}
    </div>

    <button type="submit">Save</button>
</form>
```

### Step 7: Update Toast Messages

#### Before (Django Messages)

```python
from django.contrib import messages

def your_view(request):
    messages.success(request, 'Park saved!')
    return redirect('parks:list')
```

#### After (HTMX Response)

```python
from apps.core.htmx_utils import htmx_success

def your_view(request):
    # For HTMX requests
    if request.headers.get('HX-Request'):
        return htmx_success('Park saved!')

    # For regular requests, still use messages
    messages.success(request, 'Park saved!')
    return redirect('parks:list')
```

### Step 8: Update Modals

#### Before

```html
<div class="modal" id="edit-modal">
    <div class="modal-header">
        <h2>Edit Park</h2>
        <button onclick="closeModal()">×</button>
    </div>
    <div class="modal-body">
        <!-- Content -->
    </div>
</div>
```

#### After

```django
<div x-data="{ showEditModal: false }">
    <button @click="showEditModal = true">Edit</button>

    {% include 'components/modals/modal_base.html' with
        modal_id='edit-modal'
        show_var='showEditModal'
        title='Edit Park'
        size='lg'
    %}
</div>
```

For confirmation dialogs:

```django
{% include 'components/modals/modal_confirm.html' with
    modal_id='delete-confirm'
    show_var='showDeleteModal'
    title='Delete Park'
    message='Are you sure? This cannot be undone.'
    confirm_text='Delete'
    confirm_variant='destructive'
    confirm_hx_delete='/parks/123/'
%}
```

### Step 9: Update HTMX Views

#### Before

```python
from django.http import HttpResponse
import json

def create_park(request):
    park = Park.objects.create(**form.cleaned_data)

    response = HttpResponse('')
    response['HX-Trigger'] = json.dumps({
        'showMessage': {'message': 'Park created!'}
    })
    return response
```

#### After

```python
from apps.core.htmx_utils import htmx_success, htmx_error, htmx_modal_close

def create_park(request):
    form = ParkForm(request.POST)

    if not form.is_valid():
        return htmx_error('Validation failed', status=422)

    park = form.save()

    # Simple success
    return htmx_success(f'{park.name} created!')

    # Or close modal and refresh list
    return htmx_modal_close(
        message=f'{park.name} created!',
        refresh_target='#parks-list'
    )
```

### Step 10: Add Page Meta

#### In Your View

```python
from apps.core.utils import build_meta_context

def park_detail(request, slug):
    park = get_object_or_404(Park, slug=slug)

    request.page_meta = build_meta_context(
        title=park.name,
        description=park.description,
        instance=park,
        request=request,
    )

    return render(request, 'parks/detail.html', {'park': park})
```

The meta tags are automatically rendered in the base template.

## Component Replacements

| Old Pattern | New Component |
|-------------|---------------|
| Custom page header | `components/layout/page_header.html` |
| Form field div | `forms/partials/form_field.html` |
| Form buttons | `forms/partials/form_actions.html` or `components/ui/action_bar.html` |
| Loading spinner | `htmx/components/loading_indicator.html` |
| Placeholder content | `components/skeletons/*.html` |
| Custom modal | `components/modals/modal_base.html` |
| Confirm dialog | `components/modals/modal_confirm.html` |
| Custom breadcrumbs | `components/navigation/breadcrumbs.html` |
| Status labels | `components/status_badge.html` |

## View Helper Replacements

| Old Pattern | New Helper |
|-------------|------------|
| `HttpResponse + HX-Trigger` | `htmx_success()` / `htmx_error()` |
| `HttpResponse + HX-Redirect` | `htmx_redirect()` |
| Custom modal close | `htmx_modal_close()` |
| Inline validation | `htmx_validation_response()` |
| Check HX-Request header | `is_htmx_request()` |

## Common Issues

### Issue: Breadcrumbs Not Showing

1. Ensure context processor is added to settings:

```python
TEMPLATES = [{
    'OPTIONS': {
        'context_processors': [
            # ...
            'apps.core.context_processors.breadcrumbs',
        ],
    },
}]
```

2. Ensure you set `request.breadcrumbs` in your view.

### Issue: Toast Not Appearing

1. Ensure toast container is in base template:

```django
{% include 'components/ui/toast-container.html' %}
```

2. Ensure Alpine.js is loaded and toast store is initialized.

3. For HTMX responses, use the helper functions:

```python
return htmx_success('Message here')
```

### Issue: Modal Not Closing

1. Ensure you're using the correct `show_var`:

```django
<div x-data="{ showModal: false }">
    {% include 'components/modals/modal_base.html' with show_var='showModal' %}
</div>
```

2. For HTMX responses, use:

```python
return htmx_modal_close(message='Done!')
```

### Issue: Form Validation Not Working

1. Ensure HTMX attributes are correct:

```html
<form hx-post="/create/"
      hx-target="#form-container"
      hx-swap="outerHTML">
```

2. Return proper status code on errors:

```python
if not form.is_valid():
    return render(request, 'form.html', {'form': form}, status=422)
```

### Issue: Skeleton Not Matching Content

Adjust skeleton parameters to match your content:

```django
{# For a 3-column grid with 9 cards #}
{% include 'components/skeletons/card_grid_skeleton.html' with cards=9 cols=3 %}

{# For a table with checkboxes #}
{% include 'components/skeletons/table_skeleton.html' with rows=10 columns=5 show_checkbox=True %}
```

## Testing Migrations

After migrating a template:

1. **Visual Check**: Ensure layout matches design
2. **Functionality**: Test all interactive elements
3. **Accessibility**: Test keyboard navigation and screen readers
4. **Responsive**: Check on mobile, tablet, and desktop
5. **Loading States**: Verify skeletons and indicators work
6. **Error States**: Test form validation and error messages
7. **Success States**: Verify toast notifications appear

## Rollback

If issues arise, components are designed to be backwards compatible.
You can temporarily revert to old patterns while debugging:

```django
{% comment %}
{% include 'components/layout/page_header.html' with title='Parks' %}
{% endcomment %}

<div class="page-header">
    <h1>Parks</h1>
</div>
```
