Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed frontend/public/img/bg_25.jpg
Binary file not shown.
Binary file added frontend/public/img/bg_26.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 38 additions & 35 deletions frontend/src/components/auth/authForm.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef, useState } from 'react';

import { handleCASTicket, loginUser, requestPasswordUser } from "../../services/requests/auth.service";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { handleCASTicket, loginUser, requestPasswordUser } from '../../services/requests/auth.service';
import { Button } from '../ui/button';
import { Input } from '../ui/input';

export const AuthForm = () => {
const userRef = useRef<HTMLInputElement>(null);
const [formData, setFormData] = useState({ email: "", password: "" });
const [formData, setFormData] = useState({ email: '', password: '' });
const [error, setError] = useState<string | null>(null);
const [casProcessed] = useState(() => {
return localStorage.getItem("casProcessed") === "true";
return localStorage.getItem('casProcessed') === 'true';
});

useEffect(() => {
Expand All @@ -21,7 +21,7 @@ export const AuthForm = () => {

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
setFormData((prev) => ({ ...prev, [name]: value }));
};

const handleLogin = async (e: React.FormEvent) => {
Expand All @@ -30,12 +30,12 @@ export const AuthForm = () => {
try {
const token = await loginUser(formData.email, formData.password);
if (token) {
localStorage.setItem("authToken", token);
window.location.href = "/home?login=true";
localStorage.setItem('authToken', token);
window.location.href = '/home?login=true';
}
} catch (err: any) {
console.error(err);
setError("Échec de la connexion. Vérifie ton email et ton mot de passe.");
setError('Échec de la connexion. Vérifie ton email et ton mot de passe.');
}
};

Expand All @@ -44,49 +44,48 @@ export const AuthForm = () => {
const CAS_LOGIN_URL = import.meta.env.VITE_CAS_LOGIN_URL;
const loginUrl = `${CAS_LOGIN_URL}?service=${encodeURIComponent(SERVICE_URL as string)}`;
window.location.href = loginUrl;
localStorage.setItem("casProcessed", "false");
localStorage.setItem('casProcessed', 'false');
};

const handleCASLogin = async () => {
if (window.location.pathname === "/home") return;
if (localStorage.getItem("casProcessed") === "true") return;
if (window.location.pathname === '/home') return;
if (localStorage.getItem('casProcessed') === 'true') return;

localStorage.setItem("casProcessed", "true");
localStorage.setItem('casProcessed', 'true');

const urlParams = new URLSearchParams(window.location.search);
const ticket = urlParams.get("ticket");
const ticket = urlParams.get('ticket');

if (ticket) {
try {
const { token } = await handleCASTicket(ticket);
localStorage.setItem("authToken", token);
setTimeout(() => window.location.href = "/home", 300);
localStorage.setItem('authToken', token);
setTimeout(() => (window.location.href = '/home'), 300);
} catch (error) {
console.error("CAS Login failed:", error);
setError("Authentification CAS échouée. Réessaie.");
console.error('CAS Login failed:', error);
setError('Authentification CAS échouée. Réessaie.');
}
}
};

const handlePasswordReset = async () => {
const email = prompt("Entre ton adresse email pour réinitialiser ton mot de passe :");
if (email && email.includes("@")) {
const email = prompt('Entre ton adresse email pour réinitialiser ton mot de passe :');
if (email && email.includes('@')) {
try {
const res = await requestPasswordUser(email);
if (!res.ok) alert("Un lien de réinitialisation a été envoyé à ton adresse email !");
if (!res.ok) alert('Un lien de réinitialisation a été envoyé à ton adresse email !');
} catch {
alert("Erreur lors de l'envoi de l'email. Vérifie l'adresse.");
}
} else {
alert("Adresse email invalide.");
alert('Adresse email invalide.');
}
};

return (
<div
className="relative min-h-screen flex items-center justify-center bg-no-repeat bg-cover bg-center"
style={{ backgroundImage: "url('img/bg_25.jpg')" }}
>
style={{ backgroundImage: "url('img/bg_26.png')" }}>
<div className="absolute inset-0 bg-black opacity-50"></div>
<div className="z-10 w-full max-w-md p-8 space-y-8 bg-white rounded-lg shadow-lg">
<h2 className="text-3xl font-bold text-center">Connexion</h2>
Expand All @@ -96,7 +95,9 @@ export const AuthForm = () => {
<form onSubmit={handleLogin} className="space-y-6">
<div className="space-y-4">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">Email</label>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
Email
</label>
<Input
type="email"
id="email"
Expand All @@ -108,7 +109,9 @@ export const AuthForm = () => {
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-gray-700">Mot de passe</label>
<label htmlFor="password" className="block text-sm font-medium text-gray-700">
Mot de passe
</label>
<Input
type="password"
id="password"
Expand All @@ -121,21 +124,22 @@ export const AuthForm = () => {
</div>

<div className="flex flex-col gap-4">
<Button type="submit" className="w-full py-2 bg-blue-600 text-white hover:bg-blue-700 transition">
<Button
type="submit"
className="w-full py-2 bg-blue-600 text-white hover:bg-blue-700 transition">
Connexion - Nouveau
</Button>

<Button
type="button"
className="w-full py-2 bg-gray-200 text-gray-800 hover:bg-gray-300 transition"
onClick={handlePasswordReset}
>
onClick={handlePasswordReset}>
Mot de passe oublié ?
</Button>

<p className="text-center text-sm text-gray-500">
✉️ Nouveau ? Ton compte se crée via <strong>login + mot de passe</strong>.
Vérifie ton mail pour l'activer.
✉️ Nouveau ? Ton compte se crée via <strong>login + mot de passe</strong>. Vérifie ton mail
pour l'activer.
</p>
</div>

Expand All @@ -144,13 +148,12 @@ export const AuthForm = () => {
<Button
type="button"
className="w-full py-2 bg-blue-900 text-white hover:bg-gray-700 transition"
onClick={UTT_Connexion}
>
onClick={UTT_Connexion}>
Connexion CAS - Orga / CE
</Button>
</div>
</form>
</div>
</div>
);
}
};
41 changes: 21 additions & 20 deletions frontend/src/components/auth/registrationForm.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

import { completeRegistration } from "../../services/requests/auth.service";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { completeRegistration } from '../../services/requests/auth.service';
import { Button } from '../ui/button';
import { Input } from '../ui/input';

export const RegistrationForm = () => {
const navigate = useNavigate();
const location = useLocation();
const [token, setToken] = useState<string | null>(null);

const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState(false);

useEffect(() => {
const queryParams = new URLSearchParams(location.search);
const t = queryParams.get("token");
const t = queryParams.get('token');
setToken(t);
}, [location.search]);

Expand All @@ -26,32 +26,29 @@ export const RegistrationForm = () => {
setError(null);

if (!token) {
return setError("Token invalide ou manquant.");
return setError('Token invalide ou manquant.');
}

if (password !== confirmPassword) {
return setError("Les mots de passe ne correspondent pas.");
return setError('Les mots de passe ne correspondent pas.');
}

try {
await completeRegistration(token, password);
setSuccess(true);
setTimeout(() => navigate("/"), 2000);
setTimeout(() => navigate('/'), 2000);
} catch (err: any) {
setError("Erreur lors de la validation : " + err.response.data.message);
setError('Erreur lors de la validation : ' + err.response.data.message);
}
};

return (
<div
className="relative min-h-screen flex items-center justify-center bg-no-repeat bg-cover bg-center"
style={{ backgroundImage: "url('img/bg_25.jpg')" }}
>
style={{ backgroundImage: "url('img/bg_26.png')" }}>
<div className="min-h-screen flex items-center justify-center w-full">
<div className="bg-white shadow-2xl rounded-2xl p-10 w-full max-w-md transition-all duration-300">
<h2 className="text-3xl font-bold mb-6 text-center text-gray-800">
Définir votre mot de passe
</h2>
<h2 className="text-3xl font-bold mb-6 text-center text-gray-800">Définir votre mot de passe</h2>

{error && (
<div className="text-red-600 bg-red-100 p-3 rounded mb-4 text-center flex items-center justify-center gap-2 transition-all duration-300">
Expand Down Expand Up @@ -80,7 +77,9 @@ export const RegistrationForm = () => {
</div>

<div>
<label htmlFor="confirmPassword" className="block text-sm font-medium text-gray-700 mb-1">
<label
htmlFor="confirmPassword"
className="block text-sm font-medium text-gray-700 mb-1">
Confirmer le mot de passe
</label>
<Input
Expand All @@ -93,7 +92,9 @@ export const RegistrationForm = () => {
/>
</div>

<Button type="submit" className="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 rounded transition duration-200">
<Button
type="submit"
className="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 rounded transition duration-200">
✅ Valider
</Button>
</form>
Expand All @@ -102,4 +103,4 @@ export const RegistrationForm = () => {
</div>
</div>
);
}
};
24 changes: 11 additions & 13 deletions frontend/src/components/auth/resetPasswordForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,39 @@ export const ResetPasswordForm = () => {

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const tokenFromUrl = urlParams.get("token");
const tokenFromUrl = urlParams.get('token');
if (!tokenFromUrl) {
alert("Token invalide ou manquant.");
alert('Token invalide ou manquant.');
}
setToken(tokenFromUrl);
}, []);

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!token) {
alert("Lien invalide ou expiré.");
alert('Lien invalide ou expiré.');
return;
}

if (password.length < 6) {
alert("Le mot de passe doit contenir au moins 6 caractères.");
alert('Le mot de passe doit contenir au moins 6 caractères.');
return;
}

if (password !== confirmPassword) {
alert("Les mots de passe ne correspondent pas.");
alert('Les mots de passe ne correspondent pas.');
return;
}

setLoading(true);
try {
const response = await resetPasswordUser(token, password);
if (response) {
alert("Mot de passe modifié avec succès.");
window.location.href = "/";
alert('Mot de passe modifié avec succès.');
window.location.href = '/';
}
} catch {
alert("Erreur de connexion au serveur.");
alert('Erreur de connexion au serveur.');
} finally {
setLoading(false);
}
Expand All @@ -51,8 +51,7 @@ export const ResetPasswordForm = () => {
return (
<div
className="relative min-h-screen flex items-center justify-center bg-no-repeat bg-cover bg-center"
style={{ backgroundImage: "url('img/bg_25.jpg')" }}
>
style={{ backgroundImage: "url('img/bg_26.png')" }}>
<form onSubmit={handleSubmit} className="bg-white p-8 rounded shadow-md w-full max-w-md">
<h1 className="text-2xl font-bold text-center mb-6">Réinitialiser le mot de passe</h1>

Expand Down Expand Up @@ -87,9 +86,8 @@ export const ResetPasswordForm = () => {
<button
type="submit"
disabled={loading}
className={`w-full py-2 rounded-md text-white ${loading ? "bg-gray-500" : "bg-blue-600 hover:bg-blue-700"} transition`}
>
{loading ? "Chargement..." : "Réinitialiser"}
className={`w-full py-2 rounded-md text-white ${loading ? 'bg-gray-500' : 'bg-blue-600 hover:bg-blue-700'} transition`}>
{loading ? 'Chargement...' : 'Réinitialiser'}
</button>
</form>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/notFound.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const NotFoundPage = () => {

<main
className="relative flex-1 flex items-center justify-center bg-no-repeat bg-cover bg-center px-4"
style={{ backgroundImage: "url('img/bg_25.jpg')" }}>
style={{ backgroundImage: "url('img/bg_26.png')" }}>
<div className="absolute inset-0 bg-black/55" aria-hidden="true"></div>

<Card className="relative z-10 w-full max-w-xl text-center shadow-lg">
Expand Down
Loading