"use client" import { useState, useEffect, Suspense } from "react" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Badge } from "@/components/ui/badge" import { BarChart3, Users, Trophy, TrendingUp, ArrowLeft, RotateCcw, Download, Eye, Maximize2, Minimize2, Table, Clock, RefreshCw } from "lucide-react" import Link from "next/link" import Image from "next/image" import { AuthGuard } from "@/components/auth-guard" import { useAuth } from "@/hooks/use-auth" import { DashboardHeader } from "@/components/dashboard-header" import apiClient from "@/lib/api-client" import { API_CONFIG } from "@/lib/config" import { useToast } from "@/hooks/use-toast" import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend } from 'recharts' interface VoteEvent { id: string title: string description: string start_date: string end_date: string is_active: boolean is_voting_open: boolean results_open: boolean } interface VoteEventDetails { vote_event: VoteEvent total_participants: number total_voted: number total_not_voted: number } interface Candidate { id: string vote_event_id: string name: string image_url: string description: string created_at: string updated_at: string vote_count: number } interface VoteResults { vote_event_id: string candidates: Candidate[] total_votes: number } interface ChartData { name: string votes: number percentage: number fill: string } function ResultsPageContent() { const { user } = useAuth() const { toast } = useToast() const [events, setEvents] = useState([]) const [selectedEventId, setSelectedEventId] = useState("") const [results, setResults] = useState(null) const [eventDetails, setEventDetails] = useState(null) const [loading, setLoading] = useState(false) const [eventsLoading, setEventsLoading] = useState(true) const [isFullPageChart, setIsFullPageChart] = useState(false) const [showCountdown, setShowCountdown] = useState(false) const [countdown, setCountdown] = useState(10) const [showResults, setShowResults] = useState(false) const [isFullscreen, setIsFullscreen] = useState(false) const [isRefreshing, setIsRefreshing] = useState(false) const [lastUpdated, setLastUpdated] = useState(new Date()) // Chart colors const COLORS = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#06B6D4', '#84CC16', '#F97316'] useEffect(() => { fetchEvents() }, []) // Note: URL parameter handling removed for now - can be added back later if needed useEffect(() => { if (selectedEventId) { fetchEventDetails(selectedEventId, false) fetchResults(selectedEventId, false) // Set up interval for live updates every 10 seconds const interval = setInterval(() => { fetchEventDetails(selectedEventId, true) fetchResults(selectedEventId, true) }, 10000) // 10 seconds // Cleanup interval on unmount or when selectedEventId changes return () => clearInterval(interval) } }, [selectedEventId]) useEffect(() => { let interval: NodeJS.Timeout if (showCountdown && countdown > 0) { interval = setInterval(() => { setCountdown(prev => prev - 1) }, 1000) } else if (showCountdown && countdown === 0) { // Simply transition to results - fullscreen container remains the same setShowCountdown(false) setShowResults(true) } return () => clearInterval(interval) }, [showCountdown, countdown]) // Fullscreen change listener useEffect(() => { const handleFullscreenChange = () => { const fullscreenElement = document.fullscreenElement setIsFullscreen(!!fullscreenElement) // Add/remove fullscreen styles to the event overview card const eventOverviewCard = document.querySelector('[data-fullscreen-target="event-overview"]') if (eventOverviewCard) { if (fullscreenElement === eventOverviewCard) { eventOverviewCard.classList.add('fullscreen-active') } else { eventOverviewCard.classList.remove('fullscreen-active') } } } document.addEventListener('fullscreenchange', handleFullscreenChange) return () => document.removeEventListener('fullscreenchange', handleFullscreenChange) }, []) const fetchEvents = async () => { try { setEventsLoading(true) const response = await apiClient.get(API_CONFIG.ENDPOINTS.VOTE_EVENTS) if (response.data.success) { const eventList = response.data.data.vote_events || [] setEvents(eventList) // Auto-select the first event if available if (eventList.length > 0 && !selectedEventId) { setSelectedEventId(eventList[0].id) } } } catch (error) { console.error('Error fetching events:', error) toast({ title: "Error", description: "Failed to fetch vote events", variant: "destructive" }) } finally { setEventsLoading(false) } } const fetchEventDetails = async (eventId: string, showRefreshIndicator = false) => { try { if (showRefreshIndicator) setIsRefreshing(true) const response = await apiClient.get(`/api/v1/vote-events/${eventId}/details`) if (response.data.success) { setEventDetails(response.data.data) setLastUpdated(new Date()) } } catch (error) { console.error('Error fetching event details:', error) // Only show toast on initial load, not on refresh if (!showRefreshIndicator) { toast({ title: "Error", description: "Failed to fetch event details", variant: "destructive" }) } } finally { if (showRefreshIndicator) { setTimeout(() => setIsRefreshing(false), 500) // Show indicator for at least 500ms } } } const fetchResults = async (eventId: string, showRefreshIndicator = false) => { try { if (!showRefreshIndicator) setLoading(true) if (showRefreshIndicator) setIsRefreshing(true) const response = await apiClient.get(`${API_CONFIG.ENDPOINTS.RESULTS}/${eventId}/results`) if (response.data.success) { setResults(response.data.data) setLastUpdated(new Date()) } } catch (error) { console.error('Error fetching results:', error) // Only show toast on initial load, not on refresh if (!showRefreshIndicator) { toast({ title: "Error", description: "Failed to fetch voting results", variant: "destructive" }) } } finally { if (!showRefreshIndicator) setLoading(false) if (showRefreshIndicator) { setTimeout(() => setIsRefreshing(false), 500) // Show indicator for at least 500ms } } } const getChartData = (): (ChartData & { image_url: string; id: string })[] => { if (!results) return [] return results.candidates .sort((a, b) => b.vote_count - a.vote_count) // Sort by vote count descending .map((candidate, index) => ({ name: candidate.name, votes: candidate.vote_count, percentage: results.total_votes > 0 ? (candidate.vote_count / results.total_votes) * 100 : 0, fill: COLORS[index % COLORS.length], image_url: candidate.image_url, id: candidate.id })) } const getWinner = (): Candidate | null => { if (!results || results.candidates.length === 0) return null return results.candidates.reduce((prev, current) => prev.vote_count > current.vote_count ? prev : current ) } const getEventStatus = (event: VoteEvent) => { const now = new Date() const start = new Date(event.start_date) const end = new Date(event.end_date) if (now < start) return "upcoming" if (now >= start && now <= end) return "active" return "ended" } const getStatusBadge = (event: VoteEvent) => { const status = getEventStatus(event) if (event.is_voting_open && status === "active") { return Live Voting } switch (status) { case "active": return Active case "upcoming": return Upcoming case "ended": return Ended default: return Unknown } } const handleShowResults = () => { if (!selectedEventId || !results) { toast({ title: "Error", description: "Please select an event with available results", variant: "destructive" }) return } // Check if we're in fullscreen mode from the reveal button const isInFullscreen = document.fullscreenElement !== null setShowCountdown(true) setCountdown(10) setShowResults(false) // If we were in fullscreen from reveal, maintain it by making the container fullscreen if (isInFullscreen) { setTimeout(() => { const container = document.querySelector('[data-fullscreen-target="results-container"]') if (container && !document.fullscreenElement) { container.requestFullscreen().catch(err => { console.error('Error maintaining fullscreen:', err) }) } }, 100) } } const toggleFullscreen = () => { if (!document.fullscreenElement) { // Find the event overview card and make it fullscreen const eventOverviewCard = document.querySelector('[data-fullscreen-target="event-overview"]') if (eventOverviewCard) { eventOverviewCard.requestFullscreen().catch(err => { console.error('Error attempting to enable fullscreen:', err) }) setIsFullscreen(true) } } else { document.exitFullscreen() setIsFullscreen(false) } } const selectedEvent = events.find(e => e.id === selectedEventId) const chartData = getChartData() const winner = getWinner() return (
{/* Header Section */}

Voting Results

View detailed voting results and statistics

{selectedEventId && (
{isRefreshing ? 'Updating...' : 'Live updates every 10s'}
Last updated: {lastUpdated.toLocaleTimeString()}
)}
{results && ( <>