feat: initialisation complète du projet CESIZen

- Backend Laravel 11 (API REST, JWT auth, PostgreSQL)
- Frontend Next.js 14 (React, TypeScript, Tailwind CSS)
- Docker Compose (PostgreSQL, backend, frontend)
- Modules : auth, profil, tracker émotions, informations, admin
This commit is contained in:
Azmog
2026-03-11 16:27:01 +01:00
commit e3da625927
158 changed files with 25139 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
'use client';
import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { Eye, EyeOff, Mail, Lock } from 'lucide-react';
import { useAuthStore } from '@/lib/auth-store';
import toast from 'react-hot-toast';
export default function ConnexionPage() {
const router = useRouter();
const { login } = useAuthStore();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
await login(email, password);
toast.success('Connexion réussie !');
router.push('/dashboard');
} catch (error: any) {
const message = error?.response?.data?.message || 'Identifiants incorrects';
toast.error(message);
} finally {
setLoading(false);
}
};
return (
<div className="min-h-screen flex items-center justify-center bg-linear-to-br from-candlelight-50 via-white to-malachite-50 dark:from-gray-950 dark:via-gray-900 dark:to-gray-950 px-4">
<div className="w-full max-w-md">
<div className="text-center mb-8">
<Link href="/" className="inline-block">
<h1 className="font-display text-4xl font-bold">
<span className="text-malachite-600 dark:text-malachite-400">CESI</span>
<span className="text-candlelight-500">ZEN</span>
</h1>
</Link>
<p className="text-gray-500 dark:text-gray-400 mt-2">Connectez-vous à votre compte</p>
</div>
<div className="bg-white dark:bg-gray-900 rounded-2xl shadow-xl border border-gray-100 dark:border-gray-800 p-8">
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">
Adresse email
</label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="w-full pl-11 pr-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-candlelight-500 focus:border-transparent outline-none transition-all"
placeholder="vous@exemple.fr"
/>
</div>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">
Mot de passe
</label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
id="password"
type={showPassword ? 'text' : 'password'}
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className="w-full pl-11 pr-12 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-candlelight-500 focus:border-transparent outline-none transition-all"
placeholder="Votre mot de passe"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
<button
type="submit"
disabled={loading}
className="w-full bg-candlelight-500 hover:bg-candlelight-600 disabled:opacity-50 disabled:cursor-not-allowed text-black font-semibold py-3 rounded-xl transition-all duration-200 hover:shadow-lg"
>
{loading ? (
<span className="inline-flex items-center gap-2">
<svg className="animate-spin w-5 h-5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
Connexion...
</span>
) : (
'Se connecter'
)}
</button>
</form>
<div className="mt-6 text-center text-sm text-gray-500 dark:text-gray-400">
Pas encore de compte ?{' '}
<Link href="/inscription" className="text-malachite-600 dark:text-malachite-400 font-medium hover:underline">
Créer un compte
</Link>
</div>
</div>
</div>
</div>
);
}