# HTML Views

## Overview

HTML Views are responsible for generating complete HTML pages by assembling layouts, sections, and components. They coordinate the presentation layer, bringing together data from Maestro operations and formatting it into structured HTML responses.

## Purpose

HTML Views serve several key functions:
- **Page Assembly** - Combine layouts, sections, and components into complete pages
- **Data Presentation** - Transform Maestro output into HTML structures
- **Layout Management** - Apply consistent page layouts across the application
- **Component Orchestration** - Coordinate multiple UI components

## Structure

Each HTML view typically follows this pattern:

```go
type ListPlantTasksView struct {
    Kit           *kit.Kit
    ListSection   *sections.ListSection
    NavbarSection *sections.NavbarSection
    TiledLayout   *layouts.TiledLayout
    TitleSection  *sections.TitleSection
}

func (this *ListPlantTasksView) H(out *maes.ListPlantTasksMaeOut) goc.HTML {
    mod := &layouts.LayoutMod{
        Messages: out.Extra.Messages,
        Scope:    out.Extra.Scope,
        Ctx:      out.Ctx,
    }
    return this.TiledLayout.H(this.tiling(out), mod)
}
```

## Core Methods

### Main Render Method

```go
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    mod := &layouts.LayoutMod{
        Messages: out.Extra.Messages,
        Scope:    out.Extra.Scope,
        Ctx:      out.Ctx,
        Title:    "Page Title",
    }

    return this.StructuredLayout.H(this.content(out), mod)
}
```

### Content Assembly

```go
func (this *ListPlantTasksView) tiling(out *maes.ListPlantTasksMaeOut) goc.HTML {
    component := this.Kit.Component

    return component.Dcs("flex flex-col space-y-4",
        this.NavbarSection.H(out),
        this.TitleSection.H(out),
        this.ListSection.H(out),
        this.footerSection(out),
    )
}
```

## Layout Integration

### Layout Types

```go
// Structured layout with sidebar
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    return this.StructuredLayout.H(content, mod)
}

// Tiled layout for flexible content
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    return this.TiledLayout.H(content, mod)
}

// Vertical layout for forms
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    return this.VerticalLayout.H(content, mod)
}

// Empty layout for minimal pages
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    return this.EmptyLayout.H(content, mod)
}
```

### Layout Modification

```go
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    mod := &layouts.LayoutMod{
        Messages:     out.Extra.Messages,
        Scope:        out.Extra.Scope,
        Ctx:          out.Ctx,
        Title:        "Custom Page Title",
        MetaTitle:    "SEO Title",
        Description:  "Page description for SEO",
        Keywords:     []string{"keyword1", "keyword2"},
        BodyClasses:  []string{"custom-page", "special-layout"},
    }

    return this.StructuredLayout.H(this.content(out), mod)
}
```

## Section Integration

### Common Sections

```go
func (this *SomeView) content(out *maes.SomeMaeOut) goc.HTML {
    return this.Kit.Component.Dcs("container mx-auto",
        // Navigation
        this.NavbarSection.H(out),

        // Page title
        this.TitleSection.H(out),

        // Main content
        this.mainContent(out),

        // Actions
        this.ActionSection.H(out),
    )
}
```

### Custom Sections

```go
func (this *SomeView) customSection(out *maes.SomeMaeOut) goc.HTML {
    component := this.Kit.Component

    return component.Dcs("bg-gray-100 p-4 rounded",
        component.H2("Custom Section"),
        component.P("This is custom content specific to this view"),
        this.customData(out.Data),
    )
}
```

## Component Usage

### Form Components

```go
func (this *CreatePlantView) formSection(out *maes.CreatePlantMaeOut) goc.HTML {
    return this.Kit.Component.Form(
        this.Kit.Component.FormField("text", "name", "Plant Name", out.Form.Name),
        this.Kit.Component.FormField("text", "species", "Species", out.Form.Species),
        this.Kit.Component.FormField("number", "size", "Size", out.Form.Size),
        this.Kit.Component.FormField("checkbox", "perennial", "Perennial", out.Form.Perennial),
        this.Kit.Component.SubmitButton("Create Plant"),
    )
}
```

### Table Components

```go
func (this *ListPlantsView) tableSection(out *maes.ListPlantsMaeOut) goc.HTML {
    var rows []goc.HTML

    for _, plant := range out.Plants {
        row := this.Kit.Component.TableRow(
            this.Kit.Component.TableCell(plant.Name),
            this.Kit.Component.TableCell(plant.Species),
            this.Kit.Component.TableCell(fmt.Sprintf("%d", plant.Size)),
            this.actionsCell(plant),
        )
        rows = append(rows, row)
    }

    headers := []string{"Name", "Species", "Size", "Actions"}
    return this.Kit.Component.Table(headers, rows)
}
```

### Navigation Components

```go
func (this *SomeView) navigationSection(out *maes.SomeMaeOut) goc.HTML {
    return this.Kit.Component.Nav(
        this.Kit.Component.NavLink("/plants", "Plants"),
        this.Kit.Component.NavLink("/gardens", "Gardens"),
        this.Kit.Component.NavLink("/tasks", "Tasks"),
        this.userMenu(out.User),
    )
}
```

## Data Handling

### Error Display

```go
func (this *SomeView) H(out *maes.SomeMaeOut) goc.HTML {
    content := this.mainContent(out)

    // Add error messages if present
    if len(out.Extra.Messages.Errors) > 0 {
        content = this.Kit.Component.Dcs("space-y-4",
            this.errorMessages(out.Extra.Messages.Errors),
            content,
        )
    }

    return this.StructuredLayout.H(content, mod)
}

func (this *SomeView) errorMessages(errors []string) goc.HTML {
    var errorElements []goc.HTML

    for _, error := range errors {
        errorElements = append(errorElements,
            this.Kit.Component.Dcs("bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded",
                this.Kit.Component.Text(error),
            ),
        )
    }

    return this.Kit.Component.Dcs("space-y-2", errorElements...)
}
```

### Success Messages

```go
func (this *SomeView) successMessages(messages []string) goc.HTML {
    var messageElements []goc.HTML

    for _, message := range messages {
        messageElements = append(messageElements,
            this.Kit.Component.Dcs("bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded",
                this.Kit.Component.Text(message),
            ),
        )
    }

    return this.Kit.Component.Dcs("space-y-2", messageElements...)
}
```

## Conditional Content

### User-Based Content

```go
func (this *SomeView) content(out *maes.SomeMaeOut) goc.HTML {
    content := this.mainContent(out)

    if out.User != nil && out.User.IsAdmin {
        content = this.Kit.Component.Dcs("space-y-4",
            content,
            this.adminPanel(out),
        )
    }

    return content
}
```

### Data-Based Content

```go
func (this *ListPlantsView) content(out *maes.ListPlantsMaeOut) goc.HTML {
    if len(out.Plants) == 0 {
        return this.emptyState()
    }

    return this.Kit.Component.Dcs("space-y-6",
        this.TitleSection.H(out),
        this.filtersSection(out),
        this.plantsTable(out),
        this.paginationSection(out),
    )
}

func (this *ListPlantsView) emptyState() goc.HTML {
    return this.Kit.Component.Dcs("text-center py-12",
        this.Kit.Component.H2("No plants found"),
        this.Kit.Component.P("Start by creating your first plant"),
        this.Kit.Component.Link("/plants/new", "Create Plant"),
    )
}
```

## Integration with Controllers

HTML Views are typically used in controller methods:

```go
func (gc *GardenController) List(c *gin.Context) {
    input := &maes.ListGardensMaeIn{}

    output, err := gc.ListGardensMae.Execute(c.Request.Context(), input)
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }

    html := gc.ListGardensView.H(output)
    c.Data(200, "text/html; charset=utf-8", []byte(html))
}
```

## Best Practices

### Performance
- Minimize component nesting depth
- Reuse components across views
- Avoid expensive operations in view methods

### Maintainability
- Keep views focused on presentation logic
- Extract common patterns into reusable components
- Use consistent naming conventions

### Responsive Design
- Use responsive CSS classes
- Test views across different screen sizes
- Implement mobile-first approaches

### Accessibility
- Include proper ARIA labels
- Ensure keyboard navigation works
- Provide alt text for images

## Testing HTML Views

```go
func TestListPlantsView_H(t *testing.T) {
    view := setupListPlantsView()

    output := &maes.ListPlantsMaeOut{
        Plants: []*mdl.Plant{
            {Name: "Tomato", Species: "Solanum lycopersicum"},
            {Name: "Basil", Species: "Ocimum basilicum"},
        },
    }

    html := view.H(output)

    assert.Contains(t, string(html), "Tomato")
    assert.Contains(t, string(html), "Basil")
    assert.Contains(t, string(html), "Solanum lycopersicum")
}

func TestCreatePlantView_ErrorHandling(t *testing.T) {
    view := setupCreatePlantView()

    output := &maes.CreatePlantMaeOut{
        Extra: &maes.MaeExtra{
            Messages: &maes.Messages{
                Errors: []string{"Name is required", "Size must be positive"},
            },
        },
    }

    html := view.H(output)

    assert.Contains(t, string(html), "Name is required")
    assert.Contains(t, string(html), "Size must be positive")
}
```

HTML Views provide the final layer in the presentation stack, assembling all UI components into cohesive, functional web pages that deliver great user experiences.