Alexis Bruneteau 14eff8d0da feat: Rebuild frontend with Next.js and shadcn/ui components
- Migrate from React CRA to Next.js 15 with modern architecture
- Implement comprehensive shadcn/ui component library
- Create complete dashboard system with layouts and navigation
- Build authentication pages (login, register) with proper forms
- Implement vote management pages (active, upcoming, history, archives)
- Add user profile management with security settings
- Configure Tailwind CSS with custom dark theme (accent: #e8704b)
- Setup TypeScript with strict type checking
- Backup old React-based frontend to .backups/frontend-old
- All pages compile successfully and build passes linting

Pages created:
- Home page with hero section and features
- Authentication (login/register)
- Dashboard with stats and vote cards
- Vote management (active, upcoming, history, archives)
- User profile with form validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 17:02:14 +01:00

213 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import Link from "next/link"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Mail, Lock, AlertCircle, CheckCircle } from "lucide-react"
export default function RegisterPage() {
const [formData, setFormData] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
passwordConfirm: "",
})
const [loading, setLoading] = useState(false)
const [error, setError] = useState("")
const [success, setSuccess] = useState(false)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target
setFormData(prev => ({ ...prev, [name]: value }))
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError("")
setSuccess(false)
setLoading(true)
if (formData.password !== formData.passwordConfirm) {
setError("Les mots de passe ne correspondent pas")
setLoading(false)
return
}
try {
// API call would go here
console.log("Register attempt:", formData)
// Simulate API delay
await new Promise(resolve => setTimeout(resolve, 1000))
setSuccess(true)
// Redirect to dashboard or login
} catch (err) {
setError("Une erreur s'est produite lors de l'inscription")
} finally {
setLoading(false)
}
}
return (
<div className="min-h-screen grid grid-cols-1 md:grid-cols-2">
{/* Left side - Illustration */}
<div className="hidden md:flex items-center justify-center p-8 bg-gradient-to-br from-card to-background">
<div className="text-center space-y-8 max-w-sm">
<div className="text-7xl">🗳</div>
<div className="space-y-4">
<h2 className="text-3xl font-bold">Rejoignez-nous</h2>
<p className="text-muted-foreground leading-relaxed">
Créez un compte pour participer à des élections sécurisées et transparentes
</p>
</div>
<div className="space-y-4 pt-4">
<div className="flex items-center gap-4 text-left">
<CheckCircle className="w-6 h-6 text-accent flex-shrink-0" />
<p className="font-semibold text-foreground">Inscription gratuite</p>
</div>
<div className="flex items-center gap-4 text-left">
<CheckCircle className="w-6 h-6 text-accent flex-shrink-0" />
<p className="font-semibold text-foreground">Sécurité maximale</p>
</div>
<div className="flex items-center gap-4 text-left">
<CheckCircle className="w-6 h-6 text-accent flex-shrink-0" />
<p className="font-semibold text-foreground">Aucune données</p>
</div>
</div>
</div>
</div>
{/* Right side - Form */}
<div className="flex items-center justify-center p-4 md:p-8 bg-background">
<div className="w-full max-w-sm space-y-8">
<div className="space-y-2 text-center">
<h1 className="text-3xl font-bold">S'inscrire</h1>
<p className="text-muted-foreground">Créez votre compte E-Voting</p>
</div>
<Card>
<CardContent className="pt-6">
{error && (
<div className="mb-4 p-4 rounded-md bg-destructive/10 border border-destructive/50 flex gap-3">
<AlertCircle className="w-5 h-5 text-destructive flex-shrink-0 mt-0.5" />
<div>
<p className="text-sm font-medium text-destructive">Erreur</p>
<p className="text-sm text-destructive/80">{error}</p>
</div>
</div>
)}
{success && (
<div className="mb-4 p-4 rounded-md bg-accent/10 border border-accent/50 flex gap-3">
<CheckCircle className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
<div>
<p className="text-sm font-medium text-accent">Succès</p>
<p className="text-sm text-accent/80">Votre compte a été créé avec succès</p>
</div>
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="firstName">Prénom</Label>
<Input
id="firstName"
name="firstName"
placeholder="Jean"
value={formData.firstName}
onChange={handleChange}
required
disabled={loading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="lastName">Nom</Label>
<Input
id="lastName"
name="lastName"
placeholder="Dupont"
value={formData.lastName}
onChange={handleChange}
required
disabled={loading}
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<div className="relative">
<Mail className="absolute left-3 top-3 w-5 h-5 text-muted-foreground" />
<Input
id="email"
name="email"
type="email"
placeholder="votre@email.com"
value={formData.email}
onChange={handleChange}
required
disabled={loading}
className="pl-10"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="password">Mot de passe</Label>
<div className="relative">
<Lock className="absolute left-3 top-3 w-5 h-5 text-muted-foreground" />
<Input
id="password"
name="password"
type="password"
placeholder="••••••••"
value={formData.password}
onChange={handleChange}
required
disabled={loading}
className="pl-10"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="passwordConfirm">Confirmer le mot de passe</Label>
<div className="relative">
<Lock className="absolute left-3 top-3 w-5 h-5 text-muted-foreground" />
<Input
id="passwordConfirm"
name="passwordConfirm"
type="password"
placeholder="••••••••"
value={formData.passwordConfirm}
onChange={handleChange}
required
disabled={loading}
className="pl-10"
/>
</div>
</div>
<Button type="submit" className="w-full" disabled={loading}>
{loading ? "Inscription en cours..." : "S'inscrire"}
</Button>
</form>
<p className="text-center text-sm text-muted-foreground mt-6">
Déjà un compte?{" "}
<Link href="/auth/login" className="text-accent font-medium hover:underline">
Se connecter
</Link>
</p>
</CardContent>
</Card>
</div>
</div>
</div>
)
}