# Phoenix Layout Inner Block Usage Guide

## Overview
In Phoenix layouts, the `inner_block` is a special slot that contains the actual page content being rendered inside the layout structure.

## Inner Block vs Inner Content

### Function Components (layouts.ex)
```elixir
def app(assigns) do
  ~H"""
  <main>
    {render_slot(@inner_block)}  # ← Function components use render_slot
  </main>
  """
end
```

### Template Files (.heex)
```heex
<main>
  {@inner_content}  <!-- ← Template files use @inner_content -->
</main>
```

**Important**: Both `@inner_block` and `@inner_content` refer to the same thing - the page content being rendered inside the layout.

## Updated Layouts.ex Explanation

### 1. App Layout Function Component

```elixir
attr :current_user, :map, required: false
attr :page_title, :string, default: "Dashboard"
attr :current_page, :atom, default: :dashboard
attr :container_override, :boolean, default: false
slot :inner_block, required: true  # ← This is where page content goes

def app(assigns) do
  # Conditional rendering based on authentication
  if @current_user do
    # Authenticated users get sidebar + navbar + content
    {render_slot(@inner_block)}  # ← Page content rendered here
  else
    # Guest users get simple layout + content
    {render_slot(@inner_block)}  # ← Page content rendered here
  end
end
```

### 2. Admin Layout (Legacy)

```elixir
slot :inner_block, required: true

def admin(assigns) do
  ~H"""
  <div class="admin-wrapper">
    {render_slot(@inner_block)}  # ← Page content rendered here
  </div>
  """
end
```

## How Inner Block Works

### 1. LiveView Example
```elixir
defmodule MyAppWeb.DashboardLive do
  use MyAppWeb, :live_view

  def render(assigns) do
    ~H"""
    <div class="dashboard">
      <h1>Dashboard Content</h1>
      <!-- This entire template becomes the @inner_block -->
    </div>
    """
  end
end
```

### 2. Controller View Example
```elixir
# In controller
def index(conn, _params) do
  render(conn, :index, page_title: "Home")
end

# In view template (index.html.heex)
<div class="home-page">
  <h1>Home Page Content</h1>
  <!-- This entire template becomes the @inner_block -->
</div>
```

### 3. Layout Rendering Flow
```
1. Router matches route → Controller/LiveView
2. Controller/LiveView renders its template/assigns
3. Layout wraps the rendered content in @inner_block
4. Final HTML sent to browser
```

## Current Layout System Usage

### App Layout (Recommended)
```elixir
# In LiveView mount/3
def mount(_params, session, socket) do
  socket = assign(socket, :current_page, :dashboard)
  # Layout automatically determined by authentication state
  {:ok, socket}
end
```

### Template Structure
```
app.html.heex (layout template)
├── Conditional sidebar (if @current_user)
├── Conditional navbar (if @current_user)
└── Main content area
    └── {@inner_content} ← Your page content goes here
```

## Best Practices

### 1. Use App Layout for Everything
```elixir
# ✅ Good - uses unified app layout
use MyAppWeb, :live_view  # automatically uses app layout

# ❌ Avoid - manual layout override
Phoenix.LiveView.put_layout(socket, {MyAppWeb.Layouts, :admin})
```

### 2. Page-Specific Assigns
```elixir
# In your LiveView/Controller
socket
|> assign(:current_page, :dashboard)    # For sidebar highlighting
|> assign(:page_title, "Dashboard")     # For navbar/title
|> assign(:container_override, false)   # For layout control
```

### 3. Content Organization
```heex
<!-- Your page template -->
<div class="page-content">
  <!-- Header section -->
  <div class="page-header">
    <h1>Page Title</h1>
  </div>
  
  <!-- Main content -->
  <div class="page-body">
    <!-- Your content here -->
  </div>
</div>
```

## Migration Notes

### From Admin Layout to App Layout
```elixir
# Before (old pattern)
def mount(_params, session, socket) do
  socket = Phoenix.LiveView.put_layout(socket, {MyAppWeb.Layouts, :admin})
  # ...
end

# After (new pattern)  
def mount(_params, session, socket) do
  socket = assign(socket, :current_page, :dashboard)
  # App layout handles everything automatically
  # ...
end
```

## Troubleshooting

### Issue: Content not showing
**Cause**: Missing `{render_slot(@inner_block)}` in function component
**Solution**: Add `{render_slot(@inner_block)}` where content should appear

### Issue: Layout mismatch between function and template
**Cause**: Function component and .heex template have different logic
**Solution**: Keep function component in sync with template, or remove unused function

### Issue: Missing assigns in layout
**Cause**: Layout expects assigns that aren't provided by page
**Solution**: Provide required assigns or make them optional with defaults

## Summary

The `inner_block` is the core mechanism that allows Phoenix layouts to wrap page content. In the updated system:

- **App layout**: Handles both authenticated and guest users conditionally
- **Inner block**: Contains the actual page content (dashboard, forms, etc.)
- **Consistent experience**: Same navigation and layout patterns across the app
- **Better maintainability**: Single layout system instead of multiple layout types
