@@ -16,13 +16,13 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
1616import { Label } from "@/components/ui/label" ;
1717import { Badge } from "@/components/ui/badge" ;
1818import { useToast } from "@/hooks/use-toast" ;
19- import { useAuth } from "@/hooks/useAuth " ;
20- import { isUnauthorizedError } from "@/lib/authUtils " ;
19+ import { useAuth } from "@/lib/auth-context " ;
20+ import { pollApi , type Poll } from "@/lib/pollApi " ;
2121import Link from "next/link" ;
2222
2323export default function Vote ( { params } : { params : Promise < { id : string } > } ) {
2424 const { id } = use ( params ) ;
25- const pollId = id ? Number . parseInt ( id ) : null ;
25+ const pollId = id || null ;
2626 const { toast } = useToast ( ) ;
2727 const { isAuthenticated, isLoading : authLoading } = useAuth ( ) ;
2828 const [ selectedOption , setSelectedOption ] = useState < number | null > ( null ) ;
@@ -50,13 +50,29 @@ export default function Vote({ params }: { params: Promise<{ id: string }> }) {
5050 }
5151 } , [ pollId ] ) ;
5252
53- const { data : polls = [ ] , isLoading } = { data : [ ] , isLoading : false } ; // TODO: replace with actual data fetching logic
53+ const [ selectedPoll , setSelectedPoll ] = useState < Poll | null > ( null ) ;
54+ const [ isLoading , setIsLoading ] = useState ( true ) ;
5455
55- const selectedPoll = polls . find ( ( p ) => p . id === pollId ) ;
56+ useEffect ( ( ) => {
57+ const fetchPoll = async ( ) => {
58+ if ( ! pollId ) return ;
59+
60+ try {
61+ const poll = await pollApi . getPollById ( pollId ) ;
62+ setSelectedPoll ( poll ) ;
63+ } catch ( error ) {
64+ console . error ( "Failed to fetch poll:" , error ) ;
65+ } finally {
66+ setIsLoading ( false ) ;
67+ }
68+ } ;
69+
70+ fetchPoll ( ) ;
71+ } , [ pollId ] ) ;
5672
5773 // Check if voting is still allowed
5874 const isVotingAllowed =
59- selectedPoll ?. isActive &&
75+ selectedPoll &&
6076 ( ! selectedPoll ?. deadline ||
6177 new Date ( ) < new Date ( selectedPoll . deadline ) ) ;
6278
@@ -114,13 +130,56 @@ export default function Vote({ params }: { params: Promise<{ id: string }> }) {
114130 return ( ) => clearInterval ( interval ) ;
115131 } , [ selectedPoll ?. deadline , pollExists ] ) ;
116132
117- const { data : voteStatus } = { data : null } ; // TODO: replace with actual vote status fetching logic
133+ const [ voteStatus , setVoteStatus ] = useState < { hasVoted : boolean ; vote : any } | null > ( null ) ;
134+ const [ resultsData , setResultsData ] = useState < any > ( null ) ;
135+ const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
118136
119- const { data : resultsData } = { data : null } ; // TODO: replace with actual results fetching logic
137+ // Fetch vote status and results
138+ useEffect ( ( ) => {
139+ const fetchVoteData = async ( ) => {
140+ if ( ! selectedPoll || ! pollId ) return ;
141+
142+ try {
143+ const [ voteStatusData , resultsData ] = await Promise . all ( [
144+ pollApi . getUserVote ( pollId ) ,
145+ pollApi . getPollResults ( pollId )
146+ ] ) ;
147+ setVoteStatus ( voteStatusData ) ;
148+ setResultsData ( resultsData ) ;
149+ } catch ( error ) {
150+ console . error ( "Failed to fetch vote data:" , error ) ;
151+ }
152+ } ;
120153
121- const handleVoteSubmit = ( ) => {
122- if ( selectedPoll && selectedOption !== null ) {
123- // TODO: replace with actual vote submission logic
154+ fetchVoteData ( ) ;
155+ } , [ selectedPoll , pollId ] ) ;
156+
157+ const handleVoteSubmit = async ( ) => {
158+ if ( ! selectedPoll || selectedOption === null || ! pollId ) return ;
159+
160+ setIsSubmitting ( true ) ;
161+ try {
162+ await pollApi . submitVote ( pollId , selectedOption ) ;
163+ toast ( {
164+ title : "Success!" ,
165+ description : "Your vote has been submitted" ,
166+ } ) ;
167+ // Refresh vote data
168+ const [ voteStatusData , resultsData ] = await Promise . all ( [
169+ pollApi . getUserVote ( pollId ) ,
170+ pollApi . getPollResults ( pollId )
171+ ] ) ;
172+ setVoteStatus ( voteStatusData ) ;
173+ setResultsData ( resultsData ) ;
174+ } catch ( error ) {
175+ console . error ( "Failed to submit vote:" , error ) ;
176+ toast ( {
177+ title : "Error" ,
178+ description : "Failed to submit vote. Please try again." ,
179+ variant : "destructive" ,
180+ } ) ;
181+ } finally {
182+ setIsSubmitting ( false ) ;
124183 }
125184 } ;
126185
@@ -352,13 +411,13 @@ export default function Vote({ params }: { params: Promise<{ id: string }> }) {
352411 </ p >
353412 < Badge
354413 variant = {
355- selectedPoll ?. isActive
414+ isVotingAllowed
356415 ? "success"
357416 : "warning"
358417 }
359418 className = "text-lg px-4 py-2"
360419 >
361- { selectedPoll ?. isActive
420+ { isVotingAllowed
362421 ? "Active"
363422 : "Ended" }
364423 </ Badge >
@@ -464,25 +523,25 @@ export default function Vote({ params }: { params: Promise<{ id: string }> }) {
464523 disabled = { ! isVotingAllowed }
465524 >
466525 < div className = "space-y-3" >
467- { selectedPoll . options . map ( ( option ) => (
526+ { selectedPoll . options . map ( ( option , index ) => (
468527 < div
469- key = { option . id }
528+ key = { index }
470529 className = "flex items-center space-x-3"
471530 >
472531 < RadioGroupItem
473- value = { option . id . toString ( ) }
474- id = { option . id . toString ( ) }
532+ value = { index . toString ( ) }
533+ id = { index . toString ( ) }
475534 disabled = { ! isVotingAllowed }
476535 />
477536 < Label
478- htmlFor = { option . id . toString ( ) }
537+ htmlFor = { index . toString ( ) }
479538 className = { `text-base flex-1 py-2 ${
480539 isVotingAllowed
481540 ? "cursor-pointer"
482541 : "cursor-not-allowed opacity-50"
483542 } `}
484543 >
485- { option . text }
544+ { option }
486545 </ Label >
487546 </ div >
488547 ) ) }
@@ -495,12 +554,12 @@ export default function Vote({ params }: { params: Promise<{ id: string }> }) {
495554 onClick = { handleVoteSubmit }
496555 disabled = {
497556 selectedOption === null ||
498- submitVoteMutation . isPending ||
557+ isSubmitting ||
499558 ! isVotingAllowed
500559 }
501560 className = "bg-(--crimson) hover:bg-(--crimson-50) hover:text-(--crimson) hover:border-(--crimson) border text-white px-8"
502561 >
503- { submitVoteMutation . isPending ? (
562+ { isSubmitting ? (
504563 < div className = "animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" />
505564 ) : (
506565 < VoteIcon className = "w-4 h-4 mr-2" />
0 commit comments