94 lines
3.1 KiB
React
94 lines
3.1 KiB
React
|
|
import React, { useState, useEffect } from 'react';
|
|||
|
|
import { useStore } from '../stores/store';
|
|||
|
|
|
|||
|
|
export default function Login() {
|
|||
|
|
const { login, loading, error, groupes, loadGroupes, setPage } = useStore();
|
|||
|
|
const [prenom, setPrenom] = useState('');
|
|||
|
|
const [pin, setPin] = useState('');
|
|||
|
|
const [groupeId, setGroupeId] = useState('');
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (groupes.length === 0) loadGroupes();
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (groupes.length === 1) setGroupeId(groupes[0].id);
|
|||
|
|
}, [groupes]);
|
|||
|
|
|
|||
|
|
const handleSubmit = async (e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
if (!prenom || !pin || !groupeId) return;
|
|||
|
|
try {
|
|||
|
|
await login(prenom, pin, groupeId);
|
|||
|
|
} catch {}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
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">
|
|||
|
|
<div className="text-center mb-8">
|
|||
|
|
<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>
|
|||
|
|
|
|||
|
|
<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
|
|||
|
|
type="text"
|
|||
|
|
placeholder="Prénom"
|
|||
|
|
value={prenom}
|
|||
|
|
onChange={(e) => setPrenom(e.target.value)}
|
|||
|
|
className="w-full p-4 bg-gray-50 rounded-xl text-lg border-0 focus:ring-2 focus:ring-aa-blue"
|
|||
|
|
autoComplete="off"
|
|||
|
|
autoCapitalize="words"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<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"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{error && (
|
|||
|
|
<p className="text-red-500 text-sm text-center bg-red-50 p-3 rounded-lg">{error}</p>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
<button
|
|||
|
|
type="submit"
|
|||
|
|
disabled={loading || !prenom || pin.length !== 4 || !groupeId}
|
|||
|
|
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>
|
|||
|
|
);
|
|||
|
|
}
|