|
|
||
|---|---|---|
| .gitea/workflows | ||
| assets | ||
| config | ||
| lib | ||
| priv | ||
| test | ||
| .formatter.exs | ||
| .gitignore | ||
| AGENTS.md | ||
| Dockerfile | ||
| mix.exs | ||
| mix.lock | ||
| README.md | ||
Phoenix LiveView Action Requests Demo
A demonstration of how Phoenix LiveView can replace complex multi-framework stacks (Django + React, Rails + React, etc.) with a single, elegant solution for building interactive, real-time data tables.
What This Demo Shows
This project implements a fully-featured data table with filtering, sorting, and pagination in a fraction of the code required by traditional stack combinations. What typically requires:
- Backend API (Django/Rails)
- Frontend framework (React/Vue)
- State management (Redux/Zustand)
- API client libraries (Axios/Fetch)
- TypeScript type definitions
- Multiple build tools and configs
...is accomplished here in one Phoenix LiveView module with progressive enhancement, real-time updates, and URL-based state management built in.
Why This Matters
Compared to Django + React (or similar stacks):
| Aspect | Django + React | Phoenix LiveView |
|---|---|---|
| Codebase | Split across backend/frontend | Single unified codebase |
| Languages | Python + JavaScript/TypeScript | Elixir |
| Files needed | Views, serializers, API endpoints, React components, state management, type definitions | 1 LiveView module + 1 context |
| State sync | Manual API calls, polling, or WebSocket setup | Automatic via LiveView |
| Real-time | Requires channels/WebSockets setup | Built-in |
| Progressive enhancement | Requires separate server-side rendering setup | Native |
| URL state | Manual query param handling on both ends | Declarative with handle_params/3 |
| Deployment | Two separate services | Single Elixir application |
| Build complexity | Webpack/Vite + Python packaging | Mix (built-in) |
Performance Benefits
- Reduced latency: No API round-trips, server renders diffs only
- Minimal bandwidth: LiveView sends HTML diffs, not full JSON payloads
- Efficient updates: Only changed DOM elements are updated
- No client-side state bugs: Source of truth lives on the server
Maintainability Benefits
- Single mental model: No context switching between languages/frameworks
- Fewer dependencies: No npm packages, no frontend framework updates
- Type safety: Elixir's pattern matching catches errors at compile time
- Simpler testing: Test the LiveView, not API + frontend + integration
Features Implemented
Core Functionality
- ✅ Search/Filter: Fuzzy text search on patient names
- ✅ Status Filter: Dropdown (All, Resolved, Unresolved)
- ✅ Assignment Filter: Dropdown (All, Mine, Assigned, Unassigned)
- ✅ Sorting: All columns with ascending/descending indicators
- ✅ Pagination: 25 records per page with full navigation
- ✅ URL State: All filters/sorting/pagination in URL (bookmarkable/shareable)
- ✅ Progressive Enhancement: Works with and without JavaScript
Technical Highlights
- Single LiveView module handles all user interactions
- Flop library for efficient query building
- SQLite database with proper indexes
- Real-time updates without polling or manual WebSocket setup
- Responsive design with Tailwind CSS + DaisyUI
- Theme support with light/dark modes
Database Schema
# action_requests table
id :binary_id, primary_key: true
patient_name :string
status :string
assigned_user_id :integer
delivery_scheduled_at :naive_datetime
inserted_at :utc_datetime
updated_at :utc_datetime
# Indexes
- patient_name
- status
- assigned_user_id
- inserted_at
Tech Stack
- Phoenix 1.8+ - Web framework
- LiveView - Real-time server-rendered interactions
- Flop - Filtering, ordering, and pagination
- Ecto - Database wrapper and query builder
- SQLite - Embedded database (zero-config)
- Tailwind CSS + DaisyUI - Styling
- Elixir - Language
Getting Started
Prerequisites
- Elixir 1.15+
- Erlang/OTP 26+
Setup
# Install dependencies and setup database
mix setup
# Start the Phoenix server
mix phx.server
# Or start inside IEx
iex -S mix phx.server
Visit localhost:4000 in your browser.
Seeding Data
The database is automatically seeded with 1,000,000 sample records on first run. To reset:
mix ecto.reset
Code Structure
lib/
├── action_requests_demo/
│ ├── action_requests/
│ │ └── action_request.ex # Schema definition
│ └── action_requests.ex # Context with query logic
└── action_requests_demo_web/
├── live/
│ └── action_requests_live.ex # Main LiveView (filtering, sorting, pagination)
└── router.ex # Single route
Progressive Enhancement
This app works perfectly without JavaScript:
- Forms use
method="get"andaction="/" - Filter changes trigger full page reloads via form submission
- All state persists in URL query parameters
When JavaScript is enabled:
- Forms trigger LiveView events instead of page reloads
- LiveView patches the URL and re-renders
- Updates happen in real-time with minimal data transfer
The same code handles both modes via handle_params/3 - no duplicate logic required.
Testing
# Run all tests
mix test
# Run with coverage
mix test --cover
31 comprehensive tests covering all filtering, sorting, and pagination scenarios.
Key Implementation Details
Special Filter Logic
- "Mine":
assigned_user_id = current_user_id(mocked as 1) - "Assigned":
assigned_user_id IS NOT NULL - "Unassigned":
assigned_user_id IS NULL
URL Format
All state is in the URL for bookmarking/sharing:
/?status=resolved&assignment=mine&patient_name=john&page=2&order_by=patient_name&order_directions=asc
Default Behavior
- Sort:
inserted_at DESC(newest first) - Per page: 25 records
- Current user: ID 1 (for demo purposes)
Why Elixir/Phoenix?
This demo showcases Elixir's strengths:
- Concurrency: BEAM VM handles thousands of concurrent connections effortlessly
- Fault tolerance: Process isolation means one user's error won't crash others
- Low latency: LiveView's stateful connections eliminate API overhead
- Developer productivity: Write less code, ship faster, maintain easier
- Scalability: Vertical and horizontal scaling built into the platform
Production Considerations
This is a demo application. For production use, consider:
- Authentication/authorization (currently mocked)
- Rate limiting
- Database connection pooling configuration
- CDN for static assets
- Load balancing for multiple nodes
- Monitoring and observability
Learn More
- Phoenix Framework: https://www.phoenixframework.org/
- Phoenix LiveView: https://hexdocs.pm/phoenix_live_view
- Flop: https://hexdocs.pm/flop
- Elixir: https://elixir-lang.org/
License
This demonstration project is provided as-is for educational purposes.