groupe-meditation/frontend/src/pages/Login.jsx

131 lines
4.7 KiB
React
Raw Normal View History

2026-03-04 14:01:00 -05:00
import React, { useState, useEffect } from 'react';
import { useStore } from '../stores/store';
export default function Login() {
const { login, loading, error, groupes, loadGroupes, setPage } = useStore();
2026-04-17 04:04:04 -04:00
const [courriel, setCourriel] = useState(localStorage.getItem('gm_courriel') || '');
2026-03-04 14:01:00 -05:00
const [pin, setPin] = useState('');
2026-04-17 04:04:04 -04:00
const [groupeId, setGroupeId] = useState(localStorage.getItem('gm_groupe_id') || '');
const [seSouvenir, setSeSouvenir] = useState(!!localStorage.getItem('gm_courriel'));
2026-03-04 14:01:00 -05:00
useEffect(() => {
if (groupes.length === 0) loadGroupes();
}, []);
useEffect(() => {
2026-04-17 04:04:04 -04:00
if (groupes.length === 1 && !groupeId) setGroupeId(groupes[0].id);
2026-03-04 14:01:00 -05:00
}, [groupes]);
const handleSubmit = async (e) => {
e.preventDefault();
2026-04-17 04:04:04 -04:00
if (!courriel || !pin || !groupeId) return;
2026-03-04 14:01:00 -05:00
try {
2026-04-17 04:04:04 -04:00
await login(courriel, pin, groupeId, seSouvenir);
2026-03-04 14:01:00 -05:00
} catch {}
};
2026-04-17 04:04:04 -04:00
const groupeActif = groupes.find((g) => g.id === groupeId);
2026-03-04 14:01:00 -05:00
return (
<div className="min-h-screen bg-gradient-to-b from-aa-blue to-blue-900 flex flex-col items-center justify-center p-6">
2026-04-17 04:04:04 -04:00
<div className="text-center mb-6">
2026-03-04 14:01:00 -05:00
<div className="text-5xl mb-3">☮️</div>
<h1 className="text-2xl font-bold text-white">Groupe Méditation</h1>
<p className="text-blue-200 text-sm mt-1">District 87-16 · Région 87</p>
</div>
2026-04-17 04:04:04 -04:00
{/* Infos du groupe */}
{groupeActif && (
<div className="w-full max-w-sm bg-white/10 rounded-2xl p-4 mb-4 text-blue-100 text-sm space-y-1">
{groupeActif.adresse_local && (
<p className="flex items-start gap-2">
<span>📍</span>
<span>{groupeActif.adresse_local}</span>
</p>
)}
{groupeActif.jour_reunion && (
<p className="flex items-center gap-2">
<span>📅</span>
<span>
{groupeActif.jour_reunion.charAt(0).toUpperCase() + groupeActif.jour_reunion.slice(1)}
{groupeActif.heure_reunion && ` à ${groupeActif.heure_reunion}`}
</span>
</p>
)}
{groupeActif.format_reunion && (
<p className="flex items-center gap-2">
<span>📖</span>
<span>{groupeActif.format_reunion}</span>
</p>
)}
</div>
)}
2026-03-04 14:01:00 -05:00
<form onSubmit={handleSubmit} className="w-full max-w-sm bg-white rounded-2xl shadow-xl p-6 space-y-4">
{groupes.length > 1 && (
<select
value={groupeId}
onChange={(e) => setGroupeId(e.target.value)}
className="w-full p-4 bg-gray-50 rounded-xl text-lg border-0 focus:ring-2 focus:ring-aa-blue"
>
<option value="">Choisir le groupe</option>
{groupes.map((g) => (
<option key={g.id} value={g.id}>{g.nom}</option>
))}
</select>
)}
<input
2026-04-17 04:04:04 -04:00
type="email"
placeholder="Adresse courriel"
value={courriel}
onChange={(e) => setCourriel(e.target.value)}
2026-03-04 14:01:00 -05:00
className="w-full p-4 bg-gray-50 rounded-xl text-lg border-0 focus:ring-2 focus:ring-aa-blue"
2026-04-17 04:04:04 -04:00
autoComplete="email"
inputMode="email"
2026-03-04 14:01:00 -05:00
/>
<input
type="password"
inputMode="numeric"
pattern="[0-9]*"
maxLength={4}
placeholder="PIN (4 chiffres)"
value={pin}
onChange={(e) => setPin(e.target.value.replace(/\D/g, '').slice(0, 4))}
className="w-full p-4 bg-gray-50 rounded-xl text-lg text-center tracking-[1em] border-0 focus:ring-2 focus:ring-aa-blue"
/>
2026-04-17 04:04:04 -04:00
<label className="flex items-center gap-2 text-sm text-gray-500 cursor-pointer">
<input type="checkbox" checked={seSouvenir}
onChange={(e) => setSeSouvenir(e.target.checked)}
className="rounded border-gray-300 text-aa-blue focus:ring-aa-blue" />
Se souvenir de moi
</label>
2026-03-04 14:01:00 -05:00
{error && (
<p className="text-red-500 text-sm text-center bg-red-50 p-3 rounded-lg">{error}</p>
)}
<button
type="submit"
2026-04-17 04:04:04 -04:00
disabled={loading || !courriel || pin.length !== 4 || !groupeId}
2026-03-04 14:01:00 -05:00
className="w-full p-4 bg-aa-blue text-white rounded-xl text-lg font-bold disabled:opacity-40 active:scale-[0.97] transition"
>
{loading ? '...' : 'Connexion'}
</button>
<button
type="button"
onClick={() => setPage('inscription')}
className="w-full p-3 text-aa-blue text-sm font-medium"
>
J'ai un code d'invitation →
</button>
</form>
<p className="text-blue-300 text-xs mt-6">100% logiciel libre · Hébergé au Québec</p>
</div>
);
}