# Admin Sidebar Navigation

## Overview

The admin sidebar provides navigation across all admin pages. It features collapsible sections with state persistence, active page indicators, and responsive mobile support.

**File Location:** `app/templates/admin/partials/sidebar.html`

---

## Sidebar Structure

The sidebar is organized into the following sections:

| Section | Collapsible | Pages |
|---------|-------------|-------|
| Dashboard | No | Dashboard |
| Platform Administration | Yes | Companies, Vendors, Users, Customers, Marketplace |
| Content Management | Yes | Platform Homepage, Content Pages, Vendor Themes |
| Developer Tools | Yes | Components, Icons, Testing Hub, Code Quality |
| Platform Monitoring | Yes | Import Jobs, Application Logs |
| Settings | No | Settings |

---

## Collapsible Sections

### How It Works

Sections can be expanded/collapsed by clicking the section header. The state is persisted to `localStorage` so sections remain open/closed across page navigation and browser sessions.

### State Management

**File:** `static/admin/js/init-alpine.js`

```javascript
// Default state: Platform Administration open, others closed
const defaultSections = {
    platformAdmin: true,
    contentMgmt: false,
    devTools: false,
    monitoring: false
};

// State stored in localStorage under this key
const SIDEBAR_STORAGE_KEY = 'admin_sidebar_sections';
```

### Available Methods

| Method | Description |
|--------|-------------|
| `toggleSection(section)` | Toggle a section open/closed |
| `expandSectionForCurrentPage()` | Auto-expand section containing current page |
| `openSections.platformAdmin` | Check if Platform Administration is open |
| `openSections.contentMgmt` | Check if Content Management is open |
| `openSections.devTools` | Check if Developer Tools is open |
| `openSections.monitoring` | Check if Platform Monitoring is open |

### CSS Transitions

Sections animate smoothly using CSS transitions (no plugins required):

```html
<ul
    x-show="openSections.platformAdmin"
    x-transition:enter="transition-all duration-200 ease-out"
    x-transition:enter-start="opacity-0 -translate-y-2"
    x-transition:enter-end="opacity-100 translate-y-0"
    x-transition:leave="transition-all duration-150 ease-in"
    x-transition:leave-start="opacity-100 translate-y-0"
    x-transition:leave-end="opacity-0 -translate-y-2"
    class="mt-1 overflow-hidden"
>
```

### Chevron Icon Rotation

The chevron icon rotates 180 degrees when a section is expanded:

```html
<span
    x-html="$icon('chevron-down', 'w-4 h-4 transition-transform duration-200')"
    :class="{ 'rotate-180': openSections.platformAdmin }"
></span>
```

---

## Page-to-Section Mapping

Pages are mapped to their parent sections for auto-expansion:

```javascript
const pageSectionMap = {
    // Platform Administration
    companies: 'platformAdmin',
    vendors: 'platformAdmin',
    users: 'platformAdmin',
    customers: 'platformAdmin',
    marketplace: 'platformAdmin',
    // Content Management
    'platform-homepage': 'contentMgmt',
    'content-pages': 'contentMgmt',
    'vendor-theme': 'contentMgmt',
    // Developer Tools
    components: 'devTools',
    icons: 'devTools',
    testing: 'devTools',
    'code-quality': 'devTools',
    // Platform Monitoring
    imports: 'monitoring',
    logs: 'monitoring'
};
```

---

## Complete Page Mapping

| Page | `currentPage` Value | Section | URL |
|------|---------------------|---------|-----|
| Dashboard | `'dashboard'` | (always visible) | `/admin/dashboard` |
| Companies | `'companies'` | Platform Administration | `/admin/companies` |
| Vendors | `'vendors'` | Platform Administration | `/admin/vendors` |
| Users | `'users'` | Platform Administration | `/admin/users` |
| Customers | `'customers'` | Platform Administration | `/admin/customers` |
| Marketplace | `'marketplace'` | Platform Administration | `/admin/marketplace` |
| Platform Homepage | `'platform-homepage'` | Content Management | `/admin/platform-homepage` |
| Content Pages | `'content-pages'` | Content Management | `/admin/content-pages` |
| Vendor Themes | `'vendor-theme'` | Content Management | `/admin/vendor-themes` |
| Components | `'components'` | Developer Tools | `/admin/components` |
| Icons | `'icons'` | Developer Tools | `/admin/icons` |
| Testing Hub | `'testing'` | Developer Tools | `/admin/testing` |
| Code Quality | `'code-quality'` | Developer Tools | `/admin/code-quality` |
| Import Jobs | `'imports'` | Platform Monitoring | `/admin/imports` |
| Application Logs | `'logs'` | Platform Monitoring | `/admin/logs` |
| Settings | `'settings'` | (always visible) | `/admin/settings` |

---

## Active Page Indicator

Each menu item shows a purple vertical bar when active:

```html
<li class="relative px-6 py-3">
    <!-- Purple bar indicator (shows when page is active) -->
    <span x-show="currentPage === 'vendors'"
          class="absolute inset-y-0 left-0 w-1 bg-purple-600 rounded-tr-lg rounded-br-lg"
          aria-hidden="true"></span>

    <!-- Link with active text styling -->
    <a class="inline-flex items-center w-full text-sm font-semibold transition-colors duration-150 hover:text-gray-800 dark:hover:text-gray-200"
       :class="currentPage === 'vendors' ? 'text-gray-800 dark:text-gray-100' : ''"
       href="/admin/vendors">
        <span x-html="$icon('shopping-bag')"></span>
        <span class="ml-4">Vendors</span>
    </a>
</li>
```

### Setting currentPage in Components

Each page component must set `currentPage` to match the sidebar:

```javascript
function adminVendors() {
    return {
        ...data(),                    // Inherit base (includes openSections)
        currentPage: 'vendors',       // Must match sidebar check
        // ... rest of component
    };
}
```

---

## Jinja2 Macros

The sidebar uses Jinja2 macros for DRY code:

### section_header

Creates a collapsible section header with chevron:

```jinja2
{% macro section_header(title, section_key) %}
<button
    @click="toggleSection('{{ section_key }}')"
    class="flex items-center justify-between w-full px-6 py-2 ..."
>
    <span>{{ title }}</span>
    <span x-html="$icon('chevron-down', '...')"
          :class="{ 'rotate-180': openSections.{{ section_key }} }"></span>
</button>
{% endmacro %}
```

### section_content

Wraps section items with collapse animation:

```jinja2
{% macro section_content(section_key) %}
<ul x-show="openSections.{{ section_key }}" x-transition:...>
    {{ caller() }}
</ul>
{% endmacro %}
```

### menu_item

Creates a menu item with active indicator:

```jinja2
{% macro menu_item(page_id, url, icon, label) %}
<li class="relative px-6 py-3">
    <span x-show="currentPage === '{{ page_id }}'" class="..."></span>
    <a href="{{ url }}">
        <span x-html="$icon('{{ icon }}')"></span>
        <span class="ml-4">{{ label }}</span>
    </a>
</li>
{% endmacro %}
```

### Usage Example

```jinja2
{{ section_header('Platform Administration', 'platformAdmin') }}
{% call section_content('platformAdmin') %}
    {{ menu_item('companies', '/admin/companies', 'office-building', 'Companies') }}
    {{ menu_item('vendors', '/admin/vendors', 'shopping-bag', 'Vendors') }}
{% endcall %}
```

---

## Adding a New Page

### Step 1: Add Route

Add the route in `app/routes/admin_pages.py`:

```python
@router.get("/new-page", response_class=HTMLResponse, include_in_schema=False)
async def admin_new_page(
    request: Request,
    current_user: User = Depends(get_current_admin_from_cookie_or_header),
):
    return templates.TemplateResponse(
        "admin/new-page.html",
        {"request": request, "user": current_user},
    )
```

### Step 2: Create Template

Create `app/templates/admin/new-page.html`:

```jinja2
{% extends "admin/base.html" %}
{% block title %}New Page{% endblock %}
{% block alpine_data %}adminNewPage(){% endblock %}
{% block content %}
    <!-- Your content -->
{% endblock %}
```

### Step 3: Create JavaScript Component

Create `static/admin/js/new-page.js`:

```javascript
function adminNewPage() {
    return {
        ...data(),
        currentPage: 'new-page',  // Must match sidebar
        // ...
    };
}
```

### Step 4: Add to Sidebar

Edit `app/templates/admin/partials/sidebar.html`:

```jinja2
{# Add to appropriate section #}
{{ menu_item('new-page', '/admin/new-page', 'icon-name', 'New Page') }}
```

### Step 5: Update Page-Section Map (if in collapsible section)

Edit `static/admin/js/init-alpine.js`:

```javascript
const pageSectionMap = {
    // ... existing mappings
    'new-page': 'platformAdmin',  // Add mapping
};
```

---

## Mobile Sidebar

The sidebar has a mobile version that slides in from the left:

- **Toggle:** Click hamburger menu in header
- **Close:** Click outside, press Escape, or navigate
- **State:** Controlled by `isSideMenuOpen`

```javascript
// In base data()
isSideMenuOpen: false,
toggleSideMenu() {
    this.isSideMenuOpen = !this.isSideMenuOpen
},
closeSideMenu() {
    this.isSideMenuOpen = false
}
```

---

## Testing Checklist

- [ ] Sections expand/collapse on header click
- [ ] Chevron rotates when section opens/closes
- [ ] Section state persists after page reload
- [ ] Section state persists across different pages
- [ ] Active page shows purple bar indicator
- [ ] Active page text is highlighted
- [ ] Mobile sidebar opens/closes correctly
- [ ] Collapsible sections work on mobile
- [ ] All navigation links work correctly
