mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 12:41:54 +00:00
Le formulaire email/mot de passe s'affichait seul, sans explication, quand l'API locale n'était pas démarrée (la liste démo était masquée comme si DEMO_MODE était absent). Une erreur réseau affiche désormais « L'API ne répond pas — démarrez-la avec pnpm dev » ; le 404 (pas de mode démo) reste silencieux, c'est le comportement ADR-002. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { api, clearToken, getToken, setToken } from '@/api/client';
|
|
|
|
/** Profil courant. Un 401 (jeton expiré/invalide) purge la session. */
|
|
export function useMe() {
|
|
return useQuery({
|
|
queryKey: ['me'],
|
|
enabled: !!getToken(),
|
|
retry: false,
|
|
queryFn: async () => {
|
|
const { data, response } = await api.GET('/users/me');
|
|
if (response.status === 401) {
|
|
clearToken();
|
|
throw new Error('Session expirée');
|
|
}
|
|
if (!data) throw new Error('Profil indisponible');
|
|
return data;
|
|
},
|
|
});
|
|
}
|
|
|
|
/** ADR-002 : la liste n'existe qu'en DEMO_MODE — un 404 signifie « pas de
|
|
* mode démo », le web n'affiche alors rien (null). Une ERREUR RÉSEAU, en
|
|
* revanche, signifie que l'API est injoignable : l'écran de connexion
|
|
* l'affiche clairement (isError) au lieu de masquer la démo en silence. */
|
|
export function useDemoAccounts() {
|
|
return useQuery({
|
|
queryKey: ['demo-accounts'],
|
|
retry: false,
|
|
staleTime: 5 * 60_000,
|
|
queryFn: async () => {
|
|
const { data, response } = await api.GET('/auth/demo-accounts');
|
|
if (response.status === 404) return null; // pas de mode démo : normal
|
|
if (!data) throw new Error(`API : ${response.status}`);
|
|
return data.accounts;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useLogin() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body: { email: string; password: string }) => {
|
|
const { data, error } = await api.POST('/auth/login', { body });
|
|
if (error || !data) throw new Error('Email ou mot de passe incorrect');
|
|
return data;
|
|
},
|
|
onSuccess: (data) => {
|
|
setToken(data.accessToken);
|
|
queryClient.clear();
|
|
},
|
|
});
|
|
}
|
|
|
|
/** Connexion 1 clic (et bascule de rôle en cours de session — critère < 3 s). */
|
|
export function useDemoLogin() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (userId: string) => {
|
|
const { data, error } = await api.POST('/auth/demo-login', {
|
|
body: { userId },
|
|
});
|
|
if (error || !data) throw new Error('Connexion démo impossible');
|
|
return data;
|
|
},
|
|
onSuccess: (data) => {
|
|
setToken(data.accessToken);
|
|
queryClient.clear();
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useLogout() {
|
|
const queryClient = useQueryClient();
|
|
const navigate = useNavigate();
|
|
return () => {
|
|
clearToken();
|
|
queryClient.clear();
|
|
navigate('/connexion', { replace: true });
|
|
};
|
|
}
|