14 KiB
Poll System - Complete Implementation Summary
✅ Implementation Complete!
The comprehensive poll/voting system has been fully integrated into your football club website with seamless embedding in articles and activities.
🎯 What Was Built
1. Core Poll System
Backend (Go)
- ✅ Poll model with full relationships
- ✅ Poll options and votes tracking
- ✅ RESTful API endpoints (public + admin)
- ✅ Duplicate vote prevention (IP + session)
- ✅ Real-time statistics and analytics
- ✅ Database migrations (000020, 000021)
Frontend (React + TypeScript)
- ✅ Admin poll management page (
/admin/ankety) - ✅ Public polls page (
/ankety) - ✅ Interactive voting components
- ✅ Real-time results with progress bars
- ✅ Mobile-responsive design
- ✅ Dark mode support
2. Content Integration (NEW!)
PollLinker Component
- Embedded directly in article and activity admin pages
- Link/unlink polls with one click
- View stats at a glance
- Collapsible interface
Auto-Display
- Polls automatically appear on article pages
- Polls automatically appear on event/activity pages
- No manual template editing needed
- Up to 3 polls per content item
Admin Integration Points
/admin/clanky- Article admin (Media tab)/admin/aktivity- Activity admin (bottom of modal)/admin/ankety- Dedicated poll management
📁 Files Created
Backend
internal/models/poll.go - Data models
internal/controllers/poll_controller.go - API logic
database/migrations/000020_create_polls.up.sql - Initial schema
database/migrations/000020_create_polls.down.sql - Rollback
database/migrations/000021_add_poll_relationships.up.sql - Content links
database/migrations/000021_add_poll_relationships.down.sql - Rollback
Frontend
frontend/src/services/polls.ts - API client
frontend/src/pages/admin/PollsAdminPage.tsx - Admin management
frontend/src/pages/PollsPage.tsx - Public page
frontend/src/components/polls/PollCard.tsx - Voting UI
frontend/src/components/polls/EmbeddedPoll.tsx - Content embedding
frontend/src/components/home/PollsWidget.tsx - Homepage widget
frontend/src/components/admin/PollLinker.tsx - Admin integration (NEW!)
Documentation
POLL_SYSTEM_IMPLEMENTATION.md - Technical documentation
POLL_INTEGRATION_GUIDE.md - Content linking guide
POLL_QUICK_START.md - User-friendly guide (NEW!)
POLL_SYSTEM_COMPLETE.md - This file
📁 Files Modified
Backend
internal/routes/routes.go - Added poll routes
main.go - Added AutoMigrate for poll models
Frontend
frontend/src/App.tsx - Added routes
frontend/src/components/admin/AdminSidebar.tsx - Added menu item
frontend/src/pages/ArticleDetailPage.tsx - Added EmbeddedPoll
frontend/src/pages/ActivityDetailPage.tsx - Added EmbeddedPoll
frontend/src/pages/admin/ArticlesAdminPage.tsx - Added PollLinker
frontend/src/pages/admin/AdminActivitiesPage.tsx - Added PollLinker
🚀 How It Works
For Administrators
-
Create a Poll
- Go to
/admin/ankety - Click "Nová anketa"
- Fill in title and options
- Configure settings
- Save
- Go to
-
Link to Content (Two Methods)
Method A: While Editing Content
- Edit an article (
/admin/clanky) or activity (/admin/aktivity) - Find the "Ankety" section
- Click to expand
- Select poll from dropdown
- Click "Připojit"
Method B: In Poll Settings
- While creating/editing poll in
/admin/ankety - Go to "Basic" tab
- Find "Propojení s obsahem"
- Enter article ID, event ID, or video URL
- Save
- Edit an article (
-
Poll Auto-Displays
- No additional steps needed
- Poll appears automatically on the linked content page
- Users can vote immediately
For Website Visitors
-
Find Polls
- At end of article pages
- At end of event/activity pages
- On dedicated polls page (
/ankety) - On homepage (if featured)
-
Vote
- Select option(s)
- Click "Hlasovat"
- See results immediately (based on settings)
-
View Results
- Progress bars show percentages
- Total vote count displayed
- Real-time updates
🎨 Features Overview
Poll Types
- Single Choice - Radio buttons (Man of the Match)
- Multiple Choice - Checkboxes (Pick your top 3)
- Rating - Scoring system
Security
- ✅ IP address hashing (SHA256)
- ✅ Session token tracking
- ✅ Rate limiting (10 votes/minute)
- ✅ Duplicate vote prevention
- ✅ GDPR compliant
Display Options
- Always - Everyone sees results
- After Vote - Only after user votes
- After End - Only when poll closes
- Never - Admin only
Admin Features
- Full CRUD operations
- Real-time statistics
- Vote analytics (authenticated vs guest)
- Votes by day chart
- Bulk management
- Status filtering
🔗 API Endpoints
Public
GET /api/v1/polls - List active polls
GET /api/v1/polls/:id - Get poll details
POST /api/v1/polls/:id/vote - Submit vote
GET /api/v1/polls/:id/results - Get results
Query Parameters:
?featured=true - Filter featured polls
?article_id=123 - Polls for article
?event_id=456 - Polls for event
?video_url=abc123 - Polls for video
Admin (JWT Required)
GET /api/v1/admin/polls - List all polls
GET /api/v1/admin/polls/:id - Get poll
POST /api/v1/admin/polls - Create poll
PUT /api/v1/admin/polls/:id - Update poll
DELETE /api/v1/admin/polls/:id - Delete poll
GET /api/v1/admin/polls/:id/stats - Get statistics
💾 Database Schema
polls
- id (PK)
- title, description, type, status
- start_date, end_date
- allow_multiple, max_choices
- show_results
- require_auth, allow_guest_vote
- featured
- category_id (FK)
- related_match_id
- related_article_id (FK) ← NEW!
- related_event_id (FK) ← NEW!
- related_video_url ← NEW!
- image_url
- total_votes
- created_by (FK)
- timestamps
poll_options
- id (PK)
- poll_id (FK)
- text, description, image_url
- display_order
- vote_count
- player_id (FK)
- timestamps
poll_votes
- id (PK)
- poll_id (FK)
- option_id (FK)
- user_id (FK, nullable)
- ip_hash, user_agent, session_token
- created_at
🎯 Common Use Cases
1. Man of the Match
// After match article published
{
title: "Hráč zápasu",
related_article_id: 789,
type: "single",
options: [
{ text: "Jan Novák", player_id: 12 },
{ text: "Petr Svoboda", player_id: 23 }
],
end_date: "+24h"
}
2. Event Feedback
{
title: "Jak se vám akce líbila?",
related_event_id: 456,
options: [
{ text: "Výborné! 😍" },
{ text: "Dobré 👍" },
{ text: "Průměrné 😐" }
]
}
3. Match Prediction
{
title: "Kdo vyhraje?",
related_article_id: 123,
start_date: "now",
end_date: "match_start - 30min",
show_results: "after_end"
}
🚦 Migration Steps
First Time Setup
- Backend Migration
# Automatic on app restart
# Or manually:
make migrate
- Verify Database
-- Check tables exist
SELECT * FROM polls;
SELECT * FROM poll_options;
SELECT * FROM poll_votes;
- Test in Admin Panel
- Go to
/admin/ankety - Create a test poll
- Link it to an article
- View on frontend
From Previous Poll Version
If you had the original poll system without content integration:
- Run Migration 000021
# This adds the new relationship columns
# Safe to run - won't affect existing polls
- Update Frontend
cd frontend
npm install # If needed
npm run build
- Link Existing Polls
- Go to
/admin/ankety - Edit existing polls
- Add content links in "Basic" tab
📊 Admin Panel Guide
Poll Management Page (/admin/ankety)
Main View
- List of all polls
- Filter by status (Draft, Active, Closed, Archived)
- Quick stats (vote counts, status badges)
- Actions: Edit, Delete, View Stats
Create/Edit Poll
Tab 1: Basic
- Title, description
- Type, status
- Start/end dates
- Content linking (article, event, video)
Tab 2: Options
- Add/remove options
- Option descriptions
- Display order
- Player linking (for MOTM)
Tab 3: Settings
- Multiple choice settings
- Result visibility
- Authentication requirements
- Guest voting
- Featured flag
Statistics Modal
- Total votes
- Authenticated vs guest breakdown
- Votes by day chart
- Per-option results with percentages
Article Admin Integration (/admin/clanky)
Location: Media tab (4th tab)
Features:
- Collapsible "Ankety" section
- View linked polls with stats
- Select from available polls dropdown
- One-click link/unlink
- Only shows polls not linked elsewhere
Activity Admin Integration (/admin/aktivity)
Location: Bottom of edit modal
Features:
- Same functionality as article integration
- Perfect for event feedback
- Auto-shows after event details
🎨 Frontend Components
PollCard
Interactive voting component with:
- Option selection (radio/checkbox)
- Vote submission
- Results display with progress bars
- "Voted" badge
- Responsive design
EmbeddedPoll
Content-aware poll display:
- Automatic loading based on content ID
- Multiple poll support (max 3)
- Loading states
- Empty state handling
- Doesn't render if no polls
PollLinker
Admin integration component:
- Expandable/collapsible
- Linked polls list
- Available polls dropdown
- Link/unlink actions
- Real-time updates
PollsWidget
Homepage widget:
- Featured polls only
- Configurable title
- Responsive grid
- Auto-refreshing
🔧 Configuration
Poll Settings
{
type: 'single' | 'multiple' | 'rating',
status: 'draft' | 'active' | 'closed' | 'archived',
allow_multiple: boolean,
max_choices: number (if allow_multiple),
show_results: 'always' | 'after_vote' | 'after_end' | 'never',
require_auth: boolean,
allow_guest_vote: boolean,
featured: boolean
}
Environment Variables
No additional env vars needed! Uses existing:
DATABASE_URL- PostgreSQL connectionJWT_SECRET- AuthenticationREACT_APP_API_URL- API endpoint
🐛 Troubleshooting
Poll not showing in article editor?
- Save the article first (need ID to link)
- Refresh the page
Can't link poll?
- Check poll is "active" status
- Verify poll isn't already linked elsewhere
- Create poll first in
/admin/ankety
Poll not appearing on public page?
- Check poll status is "active"
- Verify dates include current time
- Check article/event is published
- Clear browser cache
UnlinkPoll not working?
- Updated controller now properly handles null values
- GORM Save method correctly sets NULL in database
Votes not counting?
- Check rate limiting (10/minute)
- Verify poll is active
- Check browser console for errors
🎉 Success Metrics
Once deployed, you can track:
- Total polls created
- Average votes per poll
- Most popular poll types
- Engagement rates on articles with polls
- Guest vs authenticated voting ratio
View in Admin Dashboard (/admin/ankety) statistics.
📚 Documentation Quick Links
| Document | Purpose |
|---|---|
POLL_SYSTEM_IMPLEMENTATION.md |
Technical details, API specs |
POLL_INTEGRATION_GUIDE.md |
Content linking how-to |
POLL_QUICK_START.md |
User-friendly guide for admins |
POLL_SYSTEM_COMPLETE.md |
This file - full overview |
🚀 Next Steps
-
Deploy backend
# Database migrations run automatically on startup go build ./fotbal-club -
Build frontend
cd frontend npm run build -
Create first poll
- Login to admin panel
- Navigate to
/admin/ankety - Click "Nová anketa"
- Create "Test Poll"
- Link to an article
-
Verify on frontend
- View the linked article
- See poll at bottom
- Test voting
- Check results display
-
Monitor usage
- Check
/admin/anketyfor stats - Monitor engagement
- Adjust settings as needed
- Check
💡 Pro Tips
- Create polls before publishing content - Ensures immediate availability
- Use end dates - Auto-close polls after reasonable time
- Feature important polls - Shows on homepage
- Link to players - Rich display for MOTM polls
- Monitor stats regularly - Adjust strategy based on engagement
- Test guest voting - Most fans aren't logged in
- Use descriptions - Explain poll purpose in description field
- Multiple polls - You can have multiple polls per article/event
✅ Verification Checklist
- Backend migrations run successfully
- Poll routes accessible
- Admin page loads (
/admin/ankety) - Can create test poll
- Can edit poll
- Can delete poll
- Public polls page works (
/ankety) - Can vote on poll
- Results display correctly
- Article admin shows PollLinker
- Activity admin shows PollLinker
- Can link poll to article
- Can link poll to activity
- Poll appears on article page
- Poll appears on activity page
- Can unlink poll
- Statistics display correctly
- Mobile responsive
- Dark mode works
🎊 You're All Set!
The comprehensive poll system is now fully integrated and ready to engage your football club's fans. Create your first poll and watch the engagement grow!
Questions? Refer to the detailed guides or check the admin panel help section.
Version: 1.0
Implementation Date: October 2025
Last Updated: October 12, 2025