diff --git a/e-voting-system/frontend/app/dashboard/votes/active/[id]/page.tsx b/e-voting-system/frontend/app/dashboard/votes/active/[id]/page.tsx index e71a701..160233d 100644 --- a/e-voting-system/frontend/app/dashboard/votes/active/[id]/page.tsx +++ b/e-voting-system/frontend/app/dashboard/votes/active/[id]/page.tsx @@ -5,69 +5,58 @@ import Link from "next/link" import { useParams } from "next/navigation" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { ArrowLeft, Clock, Users, CheckCircle2, AlertCircle } from "lucide-react" +import { ArrowLeft, Clock, Users, CheckCircle2, AlertCircle, Loader2 } from "lucide-react" import { VotingInterface } from "@/components/voting-interface" +interface Candidate { + id: number + name: string + description?: string + order: number +} + +interface Election { + id: number + name: string + description?: string + start_date: string + end_date: string + is_active: boolean + results_published: boolean + candidates: Candidate[] +} + export default function VoteDetailPage() { const params = useParams() const voteId = params.id as string - const [election, setElection] = useState(null) + const [election, setElection] = useState(null) const [isLoading, setIsLoading] = useState(true) const [hasVoted, setHasVoted] = useState(false) const [error, setError] = useState(null) - // Mock elections data - matches the active/page.tsx - const mockElections: Record = { - "1": { - id: 1, - name: "Election Présidentielle 2025", - description: "Première manche - Scrutin dimanche", - category: "Nationale", - status: "En cours", - progress: 65, - endDate: "2025-11-06T20:00:00", - candidates: [ - { id: 1, name: "Alice Dupont", description: "Candidate progressive" }, - { id: 2, name: "Bob Martin", description: "Candidate centriste" }, - { id: 3, name: "Claire Laurent", description: "Candidate conservatrice" }, - ], - votes: 4521, - }, - } - useEffect(() => { const fetchElection = async () => { try { setIsLoading(true) setError(null) - // First try to fetch from API const token = localStorage.getItem("access_token") - try { - const response = await fetch(`/api/elections/${voteId}`, { - headers: { - Authorization: `Bearer ${token}`, - }, - }) + const response = await fetch(`/api/elections/${voteId}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) - if (response.ok) { - const data = await response.json() - setElection(data) - return - } - } catch (err) { - // Fall back to mock data + if (!response.ok) { + throw new Error("Élection non trouvée") } - // Use mock data if API fails - const mockData = mockElections[voteId] - if (mockData) { - setElection(mockData) - } else { - setError("Élection non trouvée") - } + const data = await response.json() + setElection(data) } catch (err) { - setError("Erreur lors du chargement de l'élection") + const message = err instanceof Error ? err.message : "Erreur lors du chargement" + setError(message) + setElection(null) } finally { setIsLoading(false) } @@ -89,8 +78,9 @@ export default function VoteDetailPage() { - -

Chargement...

+ + +

Chargement de l'élection...

@@ -110,7 +100,7 @@ export default function VoteDetailPage() { - +

Erreur

@@ -137,7 +127,9 @@ export default function VoteDetailPage() {

{election.name}

-

{election.description}

+ {election.description && ( +

{election.description}

+ )}
@@ -158,30 +150,34 @@ export default function VoteDetailPage() { - - Votes + + Date de fin -

{election.votes?.toLocaleString() || 0}

+

+ {new Date(election.end_date).toLocaleDateString("fr-FR")} +

- + Statut -

{election.status}

+

+ {election.is_active ? "En cours" : "Terminée"} +

{/* Voting Interface */} - {!hasVoted ? ( + {!hasVoted && election.is_active ? ( Voter @@ -199,21 +195,33 @@ export default function VoteDetailPage() { />
- ) : ( + ) : hasVoted ? (

Vote enregistré

- Votre vote a été enregistré et chiffré de manière sécurisée. + Votre vote a été enregistré dans la blockchain et chiffré de manière sécurisée.

- - Voir l'historique de vos votes → + + Voir la blockchain →
+ ) : ( + + + +
+

Élection terminée

+

+ Cette élection est terminée. Les résultats sont disponibles. +

+
+
+
)} {/* Candidates List */} @@ -224,7 +232,7 @@ export default function VoteDetailPage() {
- {election.candidates.map((candidate: any) => ( + {election.candidates.map((candidate) => (
+} export default function ActiveVotesPage() { - const activeVotes = [ - { - id: 1, - title: "Election Présidentielle 2025", - description: "Première manche - Scrutin dimanche", - category: "Nationale", - status: "En cours", - progress: 65, - endDate: "6 Nov 2025 à 20:00", - candidates: 12, - votes: 4521, - }, - ] + const [elections, setElections] = useState([]) + const [isLoading, setIsLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const fetchElections = async () => { + try { + setIsLoading(true) + setError(null) + const token = localStorage.getItem("access_token") + + const response = await fetch("/api/elections/active", { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + + if (!response.ok) { + throw new Error("Impossible de charger les élections actives") + } + + const data = await response.json() + setElections(data || []) + } catch (err) { + const message = err instanceof Error ? err.message : "Erreur lors du chargement" + setError(message) + setElections([]) + } finally { + setIsLoading(false) + } + } + + fetchElections() + }, []) + + if (isLoading) { + return ( +
+
+

Votes Actifs

+

+ Participez aux élections et scrutins en cours +

+
+ + + +

Chargement des élections actives...

+
+
+
+ ) + } + + if (error) { + return ( +
+
+

Votes Actifs

+

+ Participez aux élections et scrutins en cours +

+
+ + + +
+

Erreur

+

{error}

+
+
+
+
+ ) + } + + if (elections.length === 0) { + return ( +
+
+

Votes Actifs

+

+ Participez aux élections et scrutins en cours +

+
+ + +
📭
+

Aucune élection active

+

+ Il n'y a actuellement aucune élection en cours. Revenez bientôt. +

+
+
+
+ ) + } return (
@@ -33,66 +128,49 @@ export default function ActiveVotesPage() { {/* Filters */}
-
- {/* Votes List */} + {/* Elections List */}
- {activeVotes.map((vote) => ( - + {elections.map((election) => ( +
- {/* Title and Category */} + {/* Title */}
- {vote.title} - {vote.description} + {election.name} + {election.description && ( + {election.description} + )}
- {vote.category} + En cours
{/* Stats Row */} -
+

Candidats

-

{vote.candidates}

+

{election.candidates?.length || 0}

-

Votes

-

{vote.votes.toLocaleString()}

-
-
-

Participation

-

{vote.progress}%

-
-
- - {/* Progress Bar */} -
-
- Participation - {vote.progress}% -
-
-
+

Date de fin

+

+ {new Date(election.end_date).toLocaleDateString("fr-FR")} +

{/* Footer */}
- Ferme le {vote.endDate} + Ferme le {new Date(election.end_date).toLocaleString("fr-FR")} - +