# Page Builder Feature Plan

## Overview

Transform the static page templates into a database-driven, customizable page builder. Users will be able to add, remove, reorder, and configure page sections through a visual editor similar to the existing theme editor.

## Goals

1. Allow customization of page layouts without code changes
2. Provide real-time preview while editing
3. Support responsive editing (works on mobile and desktop)
4. Maintain theme consistency with existing design system

## Architecture

### Current State

```
PageTemplates/
├── home.html.heex     # Static: hero → category_nav → featured_products → image_text
├── collection.html.heex
├── pdp.html.heex
├── cart.html.heex
├── about.html.heex
├── contact.html.heex
└── error.html.heex
```

### Future State

```
Database (page_layouts table)
├── page: "home"
│   └── sections: [
│       {type: "hero", order: 1, settings: {...}},
│       {type: "category_nav", order: 2, settings: {...}},
│       {type: "featured_products", order: 3, settings: {...}},
│       {type: "image_text", order: 4, settings: {...}}
│   ]
├── page: "about"
│   └── sections: [...]
└── ...

PageRenderer module
├── render_page/2        # Renders page from layout + data
└── render_section/1     # Dispatches to component by type
```

## Data Model

### PageLayout Schema

```elixir
defmodule SimpleshopTheme.Content.PageLayout do
  use Ecto.Schema

  schema "page_layouts" do
    field :page_type, :string  # "home", "about", "collection", etc.
    field :name, :string       # Display name for the layout
    field :is_default, :boolean, default: false

    has_many :sections, SimpleshopTheme.Content.PageSection

    timestamps()
  end
end
```

### PageSection Schema

```elixir
defmodule SimpleshopTheme.Content.PageSection do
  use Ecto.Schema

  schema "page_sections" do
    field :section_type, :string   # "hero", "featured_products", etc.
    field :order, :integer
    field :settings, :map          # JSON settings for the section
    field :enabled, :boolean, default: true

    belongs_to :page_layout, SimpleshopTheme.Content.PageLayout

    timestamps()
  end
end
```

### Section Types Registry

```elixir
defmodule SimpleshopTheme.Content.SectionTypes do
  @sections %{
    "hero" => %{
      name: "Hero Banner",
      component: &SimpleshopThemeWeb.ShopComponents.hero_section/1,
      settings_schema: %{
        title: %{type: :string, default: "Welcome"},
        description: %{type: :string, default: ""},
        cta_text: %{type: :string, default: "Shop now"},
        cta_page: %{type: :string, default: "collection"},
        background: %{type: :select, options: [:default, :sunken], default: :default}
      },
      allowed_on: [:home, :about, :contact, :error]
    },
    "featured_products" => %{
      name: "Featured Products",
      component: &SimpleshopThemeWeb.ShopComponents.featured_products_section/1,
      settings_schema: %{
        title: %{type: :string, default: "Featured products"},
        product_count: %{type: :integer, default: 8}
      },
      allowed_on: [:home]
    },
    "category_nav" => %{
      name: "Category Navigation",
      component: &SimpleshopThemeWeb.ShopComponents.category_nav/1,
      settings_schema: %{},
      allowed_on: [:home]
    },
    "image_text" => %{
      name: "Image + Text Block",
      component: &SimpleshopThemeWeb.ShopComponents.image_text_section/1,
      settings_schema: %{
        title: %{type: :string},
        description: %{type: :text},
        image_url: %{type: :image},
        link_text: %{type: :string},
        link_page: %{type: :string}
      },
      allowed_on: [:home, :about]
    },
    "content_body" => %{
      name: "Rich Text Content",
      component: &SimpleshopThemeWeb.ShopComponents.content_body/1,
      settings_schema: %{
        image_url: %{type: :image},
        content: %{type: :rich_text}
      },
      allowed_on: [:about, :contact]
    },
    "reviews_section" => %{
      name: "Customer Reviews",
      component: &SimpleshopThemeWeb.ShopComponents.reviews_section/1,
      settings_schema: %{},
      allowed_on: [:pdp]
    },
    "related_products" => %{
      name: "Related Products",
      component: &SimpleshopThemeWeb.ShopComponents.related_products_section/1,
      settings_schema: %{},
      allowed_on: [:pdp]
    }
  }
end
```

## Page Renderer

```elixir
defmodule SimpleshopThemeWeb.PageRenderer do
  use Phoenix.Component
  import SimpleshopThemeWeb.ShopComponents

  alias SimpleshopTheme.Content.SectionTypes

  @doc """
  Renders a page from its layout and data context.
  """
  def render_page(assigns) do
    ~H"""
    <div class="shop-container min-h-screen" style="...">
      <.skip_link />
      <%= if @theme_settings.announcement_bar do %>
        <.announcement_bar theme_settings={@theme_settings} />
      <% end %>

      <.shop_header {...} />

      <main id="main-content">
        <%= for section <- @page_layout.sections do %>
          <.render_section
            section={section}
            data={@data}
            theme_settings={@theme_settings}
            mode={@mode}
          />
        <% end %>
      </main>

      <.shop_footer theme_settings={@theme_settings} mode={@mode} />
      <.cart_drawer {...} />
      <.search_modal {...} />
    </div>
    """
  end

  defp render_section(assigns) do
    section_config = SectionTypes.get(assigns.section.section_type)
    component = section_config.component
    settings = Map.merge(section_config.default_settings, assigns.section.settings)

    assigns = assign(assigns, :settings, settings)

    ~H"""
    <%= if @section.enabled do %>
      <%= component.(@settings |> Map.merge(%{mode: @mode, data: @data})) %>
    <% end %>
    """
  end
end
```

## Editor UI

### Layout Structure

```
┌─────────────────────────────────────────────────────────────┐
│ Desktop (≥1024px)                                           │
├───────────────────┬─────────────────────────────────────────┤
│                   │                                         │
│   Section List    │         Live Preview                    │
│   ┌───────────┐   │                                         │
│   │ Hero      │   │   ┌─────────────────────────────────┐   │
│   │ ≡ ✎ ✕    │   │   │                                 │   │
│   └───────────┘   │   │     [Hero Section Preview]      │   │
│   ┌───────────┐   │   │                                 │   │
│   │ Products  │   │   ├─────────────────────────────────┤   │
│   │ ≡ ✎ ✕    │   │   │                                 │   │
│   └───────────┘   │   │   [Products Section Preview]    │   │
│   ┌───────────┐   │   │                                 │   │
│   │ Image+Text│   │   └─────────────────────────────────┘   │
│   │ ≡ ✎ ✕    │   │                                         │
│   └───────────┘   │                                         │
│                   │                                         │
│   [+ Add Section] │                                         │
│                   │                                         │
└───────────────────┴─────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Mobile (<1024px)                                            │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Page: Home                              [Preview] ▼ │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Sections:                                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ ≡  Hero                                    ✎  ✕    │    │
│  └─────────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ ≡  Featured Products                       ✎  ✕    │    │
│  └─────────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ ≡  Image + Text                            ✎  ✕    │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  [+ Add Section]                                            │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  [Preview Panel - expandable/collapsible]                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

### Key Interactions

1. **Drag & Drop Reordering**: Sections can be reordered via drag handles (≡)
2. **Edit Settings**: Clicking ✎ opens settings panel for that section
3. **Remove Section**: Clicking ✕ removes section (with confirmation)
4. **Add Section**: Opens modal/drawer with available section types
5. **Live Preview**: Updates in real-time as changes are made
6. **Undo/Redo**: Track changes for undo capability (optional)

### Settings Panel

When editing a section, show a form based on its `settings_schema`:

```
┌─────────────────────────────────────────┐
│ Edit: Hero Banner                    ✕  │
├─────────────────────────────────────────┤
│                                         │
│ Title                                   │
│ ┌─────────────────────────────────────┐ │
│ │ Original designs, printed on demand │ │
│ └─────────────────────────────────────┘ │
│                                         │
│ Description                             │
│ ┌─────────────────────────────────────┐ │
│ │ From art prints to apparel...       │ │
│ └─────────────────────────────────────┘ │
│                                         │
│ Button Text                             │
│ ┌─────────────────────────────────────┐ │
│ │ Shop the collection                 │ │
│ └─────────────────────────────────────┘ │
│                                         │
│ Button Link                             │
│ ┌─────────────────────────────────────┐ │
│ │ collection                       ▼  │ │
│ └─────────────────────────────────────┘ │
│                                         │
│ Background Style                        │
│ ○ Default   ● Sunken                    │
│                                         │
├─────────────────────────────────────────┤
│          [Cancel]  [Save Changes]       │
└─────────────────────────────────────────┘
```

## Implementation Phases

### Phase 1: Data Model & Migration
- Create `page_layouts` and `page_sections` tables
- Create Ecto schemas
- Create seed data from current static templates
- Add context functions (CRUD)

### Phase 2: Page Renderer
- Create `PageRenderer` module
- Create `SectionTypes` registry
- Update shop LiveViews to use renderer
- Update preview to use renderer
- Ensure backward compatibility (fallback to static if no layout)

### Phase 3: Editor UI - Read Only
- Create `PageEditorLive` LiveView
- Display current sections in list
- Show live preview
- Page selector dropdown

### Phase 4: Editor UI - Basic Editing
- Add/remove sections
- Drag & drop reordering (using sortable.js or similar)
- Save changes to database

### Phase 5: Section Settings
- Settings panel component
- Dynamic form generation from schema
- Real-time preview updates

### Phase 6: Polish & UX
- Undo/redo support
- Keyboard shortcuts
- Mobile-optimized editing
- Loading states
- Error handling

## Technical Considerations

### LiveView Communication

The editor needs to:
1. Load page layout on mount
2. Send updates on reorder/add/remove
3. Update preview in real-time

Using `phx-hook` for drag-and-drop and `push_event` for preview updates.

### Caching

Page layouts should be cached since they change infrequently:
- ETS cache similar to `CSSCache`
- Invalidate on save

### Migration Path

1. Deploy data model
2. Seed current layouts as "default" layouts
3. Deploy renderer (uses defaults if no custom layout)
4. Deploy editor
5. Users can customize

### Permissions

- Only authenticated admins can edit layouts
- Consider draft/published states for layouts
- Preview unpublished changes before going live

## Open Questions

1. Should users be able to create multiple layouts per page type (A/B testing)?
2. Should sections support nesting (e.g., columns within a section)?
3. How to handle page-specific data (e.g., PDP needs product, collection needs filter state)?
4. Should there be a "reset to default" option?

## Dependencies

- `sortable.js` or similar for drag-and-drop
- Possibly `@dnd-kit/sortable` if using JS framework
- JSON schema validation for settings

## Related Files

- `lib/simpleshop_theme_web/components/shop_components.ex` - Existing section components
- `lib/simpleshop_theme_web/components/page_templates/` - Current static templates (will become defaults)
- `lib/simpleshop_theme_web/live/theme_live/index.ex` - Theme editor (reference implementation)
