first commit
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
# TankStopp Templ Optimization
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the optimization of TankStopp's template system using `a-h/templ` - a compile-time template system for Go that generates type-safe HTML templates.
|
||||
|
||||
## Migration Summary
|
||||
|
||||
The application has been migrated from traditional HTML templates to `a-h/templ` templates, providing:
|
||||
|
||||
- **Type Safety**: Templates are compiled to Go code with full type checking
|
||||
- **Performance**: Templates are compiled at build time, eliminating runtime parsing
|
||||
- **Component Reusability**: Modular components that can be composed together
|
||||
- **Developer Experience**: IDE support, auto-completion, and compile-time error checking
|
||||
|
||||
## Project Structure
|
||||
|
||||
The new template organization follows a clean architecture:
|
||||
|
||||
```
|
||||
tankstopp/internal/views/
|
||||
├── components/
|
||||
│ ├── layout.templ # Base layout, navbar, footer, cards, etc.
|
||||
│ ├── forms.templ # Form components, inputs, buttons
|
||||
│ └── icons.templ # Icon components with SVG definitions
|
||||
└── pages/
|
||||
├── auth.templ # Authentication pages (login, register)
|
||||
├── dashboard.templ # Dashboard page with statistics
|
||||
├── fuelstops.templ # Add/edit fuel stop pages
|
||||
├── vehicles.templ # Vehicle management pages
|
||||
└── settings.templ # Settings page
|
||||
```
|
||||
|
||||
## Component Architecture
|
||||
|
||||
### Layout Components (`components/layout.templ`)
|
||||
|
||||
#### Base Layout
|
||||
```go
|
||||
templ BaseLayout(title string, user *models.User, username string) {
|
||||
// Full HTML document structure with navbar, footer, and content area
|
||||
}
|
||||
```
|
||||
|
||||
#### Navigation Components
|
||||
- `Navbar()` - Main navigation bar
|
||||
- `NavItem()` - Individual navigation items
|
||||
- `UserDropdown()` - User account dropdown
|
||||
- `Footer()` - Application footer
|
||||
|
||||
#### UI Components
|
||||
- `Card()` - Reusable card component
|
||||
- `Alert()` - Alert messages (success, error, warning, info)
|
||||
- `EmptyState()` - Empty state placeholder
|
||||
- `PageHeader()` - Page header with title and subtitle
|
||||
- `Badge()` - Status badges
|
||||
- `ProgressBar()` - Progress indicators
|
||||
- `Modal()` - Modal dialogs
|
||||
- `Tabs()` - Tab navigation
|
||||
- `Pagination()` - Pagination controls
|
||||
|
||||
### Form Components (`components/forms.templ`)
|
||||
|
||||
#### Input Components
|
||||
- `Input()` - Basic text inputs
|
||||
- `NumberInput()` - Number inputs with validation
|
||||
- `DateInput()` - Date picker inputs
|
||||
- `TextArea()` - Multi-line text areas
|
||||
- `Select()` - Dropdown selects
|
||||
- `PasswordInput()` - Password inputs with visibility toggle
|
||||
|
||||
#### Specialized Selects
|
||||
- `CurrencySelect()` - Currency dropdown
|
||||
- `VehicleSelect()` - Vehicle dropdown
|
||||
- `FuelTypeSelect()` - Fuel type dropdown
|
||||
|
||||
#### Form Layout
|
||||
- `Form()` - Form wrapper
|
||||
- `FormGroup()` - Input group with label and hints
|
||||
- `FormRow()` - Form row wrapper
|
||||
- `FormCol()` - Form column wrapper
|
||||
- `FormButtons()` - Form action buttons
|
||||
- `InputGroup()` - Input with prefix/suffix
|
||||
|
||||
### Icon Components (`components/icons.templ`)
|
||||
|
||||
Comprehensive icon system with 40+ icons:
|
||||
- `Icon(name, size)` - Basic icon component
|
||||
- `IconWithClass(name, size, class)` - Icon with custom classes
|
||||
|
||||
Available icons include: fuel, plus, home, car, settings, location, edit, trash, save, user, lock, etc.
|
||||
|
||||
## Page Templates
|
||||
|
||||
### Authentication Pages (`pages/auth.templ`)
|
||||
- `LoginPage()` - User login form
|
||||
- `RegisterPage()` - User registration form
|
||||
- `AuthLayout()` - Shared layout for auth pages
|
||||
|
||||
### Dashboard (`pages/dashboard.templ`)
|
||||
- `DashboardPage()` - Main dashboard with statistics and fuel stops table
|
||||
- `FuelStopsTable()` - Reusable fuel stops table component
|
||||
- `DashboardScript()` - JavaScript for dashboard functionality
|
||||
|
||||
### Fuel Stops (`pages/fuelstops.templ`)
|
||||
- `AddFuelStopPage()` - Add new fuel stop form
|
||||
- `EditFuelStopPage()` - Edit existing fuel stop form
|
||||
- `AddFuelStopScript()` - JavaScript for form functionality including:
|
||||
- Auto-calculation of total costs
|
||||
- Current date/time defaults
|
||||
- Nearby gas station finder using Overpass API
|
||||
- Form validation
|
||||
|
||||
### Vehicles (`pages/vehicles.templ`)
|
||||
- `VehiclesPage()` - Vehicle management dashboard
|
||||
- `VehicleCard()` - Individual vehicle card component
|
||||
- `AddVehiclePage()` - Add new vehicle form
|
||||
- `EditVehiclePage()` - Edit vehicle form
|
||||
- `VehicleBrandSelect()` - Vehicle brand dropdown
|
||||
- Helper functions for vehicle statistics
|
||||
|
||||
### Settings (`pages/settings.templ`)
|
||||
- `SettingsPage()` - Comprehensive settings page with:
|
||||
- Profile settings
|
||||
- Application preferences
|
||||
- Security settings
|
||||
- Data management (import/export)
|
||||
- Account management
|
||||
- `SettingsScript()` - JavaScript for settings functionality
|
||||
|
||||
## JavaScript Integration
|
||||
|
||||
The templ templates include embedded JavaScript using the `script` template type:
|
||||
|
||||
```go
|
||||
script DashboardScript() {
|
||||
function applyFilters() {
|
||||
// JavaScript functionality
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This approach provides:
|
||||
- Type-safe JavaScript embedding
|
||||
- Scoped functionality per page
|
||||
- Compile-time validation of JavaScript references
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Page Structure
|
||||
```go
|
||||
templ MyPage(user *models.User, data MyData) {
|
||||
@components.BaseLayout("My Page", user, user.Username) {
|
||||
@components.PageHeader("Subtitle", "My Page Title")
|
||||
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
@components.Card("Card Title", "icon-name") {
|
||||
// Card content
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Form with Validation
|
||||
```go
|
||||
templ MyForm(data FormData) {
|
||||
@components.Card("Form Title", "form-icon") {
|
||||
@components.Form("post", "/submit") {
|
||||
@components.FormGroup("Field Label", "Help text") {
|
||||
@components.Input("field_name", "text", "Placeholder", data.Value, true)
|
||||
}
|
||||
|
||||
@components.FormButtons("/cancel", "Save", "save")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Data Table
|
||||
```go
|
||||
templ DataTable(items []Item) {
|
||||
@components.TableResponsive() {
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Column 1</th>
|
||||
<th>Column 2</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
for _, item := range items {
|
||||
<tr>
|
||||
<td>{ item.Field1 }</td>
|
||||
<td>{ item.Field2 }</td>
|
||||
<td>
|
||||
@components.ButtonGroup() {
|
||||
@components.EditButton("/edit/" + item.ID)
|
||||
@components.DeleteButton("/delete/" + item.ID, item.Name)
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Build Integration
|
||||
|
||||
To generate the Go code from templ files:
|
||||
|
||||
```bash
|
||||
# Install templ CLI
|
||||
go install github.com/a-h/templ/cmd/templ@latest
|
||||
|
||||
# Generate templates
|
||||
templ generate
|
||||
|
||||
# Or use the shorthand
|
||||
templ fmt . # Format templates
|
||||
templ generate . # Generate Go code
|
||||
```
|
||||
|
||||
## Handler Integration
|
||||
|
||||
In your HTTP handlers, use the generated template functions:
|
||||
|
||||
```go
|
||||
func DashboardHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Get data...
|
||||
|
||||
// Render template
|
||||
component := pages.DashboardPage(user, username, stops, vehicles, totalStops, totalCost, avgConsumption, lastFillUp)
|
||||
component.Render(r.Context(), w)
|
||||
}
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### Performance
|
||||
- Templates are compiled to Go code at build time
|
||||
- No runtime template parsing
|
||||
- Minimal memory allocation
|
||||
- Type-safe rendering
|
||||
|
||||
### Developer Experience
|
||||
- Full IDE support with auto-completion
|
||||
- Compile-time error checking
|
||||
- Refactoring support
|
||||
- Hot reload during development
|
||||
|
||||
### Maintainability
|
||||
- Component-based architecture
|
||||
- Clear separation of concerns
|
||||
- Reusable UI components
|
||||
- Consistent styling and behavior
|
||||
|
||||
### Security
|
||||
- Automatic HTML escaping
|
||||
- XSS protection by default
|
||||
- Type-safe data binding
|
||||
- Compile-time validation
|
||||
|
||||
## Migration from HTML Templates
|
||||
|
||||
### Before (HTML Templates)
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.Title}} - TankStopp</title>
|
||||
<!-- CSS links -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navbar HTML -->
|
||||
<div class="page-body">
|
||||
{{range .Items}}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4>{{.Name}}</h4>
|
||||
<p>{{.Description}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<!-- Footer HTML -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### After (Templ Templates)
|
||||
```go
|
||||
templ MyPage(title string, items []Item) {
|
||||
@components.BaseLayout(title, user, username) {
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
for _, item := range items {
|
||||
@components.Card(item.Name, "icon") {
|
||||
<p>{ item.Description }</p>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Component Composition**: Build complex UIs by composing smaller components
|
||||
2. **Type Safety**: Leverage Go's type system for template data
|
||||
3. **Reusability**: Create reusable components for common UI patterns
|
||||
4. **Performance**: Use templ's compile-time optimization
|
||||
5. **Maintainability**: Keep templates focused and well-organized
|
||||
6. **Security**: Rely on templ's automatic escaping and validation
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- **Internationalization**: Add multi-language support
|
||||
- **Theming**: Dynamic theme switching
|
||||
- **Progressive Enhancement**: Enhanced JavaScript functionality
|
||||
- **Accessibility**: ARIA labels and keyboard navigation
|
||||
- **Performance Monitoring**: Template rendering metrics
|
||||
|
||||
## Conclusion
|
||||
|
||||
The migration to `a-h/templ` provides a modern, type-safe, and performant template system that improves developer experience while maintaining excellent runtime performance. The component-based architecture makes the application more maintainable and provides a solid foundation for future enhancements.
|
||||
Reference in New Issue
Block a user