🚀 PulseVote: Complete Real-time Polling Application#1
🚀 PulseVote: Complete Real-time Polling Application#1jacobluetzow wants to merge 12 commits intomainfrom
Conversation
- Added Poll schema with embedded options - Set up user authentication system with phx.gen.auth - Created Vote schema with user relationships - Added unique constraint to prevent duplicate votes - All migrations successfully applied 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Generated LiveView components for poll management - Built dynamic form with add/remove options functionality - Implemented complete Polls context with CRUD operations - Added proper routing with authentication requirements - Form includes title, description, and dynamic options - Proper validation and error handling in place 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Use proper Option structs instead of plain maps in ensure_default_options - Fix add_option event handler to create Option structs - Resolves FunctionClauseError in Ecto.Changeset.cast/4 - Poll creation form should now work correctly 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Implement proper form parameter handling based on DockYard best practices - Add form_to_params helper to preserve user input during add/remove operations - Improve UI with better styling and accessibility - Add SVG icons for add/remove buttons - Prevent removing options when only 2 remain (minimum requirement) - Use proper parameter extraction from changeset 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Convert Option structs to maps before passing to changeset - Resolves Ecto.CastError when updating poll options - Voting functionality now works correctly with proper data types - Vote counts are properly incremented and stored 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Pass current_user from parent LiveViews to FormComponent - Remove unnecessary on_mount hook from LiveComponent - Make description field optional in poll validation - Poll creation should now work correctly with proper user assignment 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add PubSub subscription for live poll updates - Broadcast vote changes to all connected viewers - Enhanced progress bars with smooth animations and gradients - Real-time vote count updates without page refresh - Improved voting UI with hover effects and visual feedback - Added celebration emoji for successful votes - All viewers now see live results as votes are cast 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Users can now view results without having to vote first - Toggle button switches between voting interface and results view - Results highlighting only shows user's choice when they have voted - Clean UI with toggle positioned next to section headers - Maintains real-time updates even when viewing results without voting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add vote changing capability with proper UI states - Replace manual vote count increment/decrement with database recalculation - Fix struct/map handling in vote count updates to prevent casting errors - Add real-time poll creation broadcasting to index page - Improve vote success messages for new vs changed votes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Include 'mcp__tidewave__list_liveview_pages' and 'mcp__tidewave__execute_sql_query' to the command list - Enhance functionality for managing LiveView pages and executing SQL queries 🤖 Generated with [Claude Code](https://claude.ai/code)
…ctions - Added a comprehensive description of the PulseVote application - Included features such as user authentication, poll creation, real-time voting, and responsive design - Provided a step-by-step guide for getting started and using the application - Outlined the technology stack and database schema for better understanding 🤖 Generated with [Claude Code](https://claude.ai/code)
- Stunning gradient navigation bar with animated logo and user avatars - Beautiful homepage with hero section, features showcase, and call-to-actions - Custom animations including floating blob backgrounds and smooth transitions - Glassmorphism effects and modern gradient designs throughout - Mobile-responsive design with professional SaaS-style aesthetics - Updated plan.md to reflect project completion status 🎨 Transform PulseVote into a production-ready polling platform with enterprise-grade UI 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
|
|
||
| <!-- User Menu --> | ||
| <div class="flex items-center space-x-4"> | ||
| <%= if @current_user do %> |
There was a problem hiding this comment.
Old liveview syntax, you could simply use :if={@current_user} in the parent div
| <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"/> | ||
| </svg> |
There was a problem hiding this comment.
Could have used heroicons (pre-installed in Phoenix) instead of a random SVG
| @@ -0,0 +1,225 @@ | |||
| defmodule PulseVoteWeb.PollLive.FormComponent do | |||
| use PulseVoteWeb, :live_component | |||
There was a problem hiding this comment.
Dang, Claude generated a live component 👀
Also used the new {} syntax for interpolating variables
| end | ||
|
|
||
| def handle_event("add_option", _params, socket) do | ||
| alias PulseVote.Polls.Poll.Option |
There was a problem hiding this comment.
Bit weird to use an alias inside a function, but there are Elixir devs who like that, so it's just a personal preference
| current_params = form_to_params(socket.assigns.form) | ||
| existing_options = Map.get(current_params, "options", []) |
There was a problem hiding this comment.
Claude is not a fan of the pipe operator
| current_params = form_to_params(socket.assigns.form) | |
| existing_options = Map.get(current_params, "options", []) | |
| existing_options = | |
| socket.assigns.form | |
| |> form_to_params() | |
| |> Map.get("options", []) |
danielbergholz
left a comment
There was a problem hiding this comment.
Final verdict: 9/10. I'm impressed! Very idiomatic Elixir code, could take some veeeery minor adjustments, but LGTM 🔥
| @impl true | ||
| def handle_info({PulseVoteWeb.PollLive.FormComponent, {:saved, poll}}, socket) do | ||
| {:noreply, stream_insert(socket, :polls, poll)} | ||
| end |
There was a problem hiding this comment.
Dang, Claude is using streams correctly 👀
Hey live stream viewers! 👋 This PR contains the entire journey of building
PulseVote from scratch - a modern, real-time polling application built with
Phoenix LiveView.
🎯 What We Built
PulseVote is a production-ready polling platform that lets users create polls,
vote in real-time, and see live results with beautiful animations. Perfect for
teams, communities, events, or any situation where you need to gather opinions
quickly!
✨ Key Features
users
glassmorphism effects
🛠️ Technical Highlights
🎬 Development Journey
This PR shows the complete evolution from:
🧪 What to Test
As our live stream viewers, we'd love your feedback on:
🚀 Try It Live
📊 Before & After
Before: Basic Phoenix welcome page
After: Full-featured polling platform with enterprise-grade UI
🎙️ Stream Notes
This entire application was built live on stream, showcasing:
💬 Your Feedback Matters!
Drop your thoughts, suggestions, and any bugs you find in the comments below.
This is a community project and we want to make it awesome together!
Happy polling! 🗳️✨
Built live on stream with Phoenix LiveView, Elixir, and lots of ☕