Files
WikiRush/app/components/AuthModal.tsx
T
jessy-david-dev dc09658fdb feat: add user accounts, authentication, and game history with Prisma 7
- Implement user registration and login with NextAuth v5 (email/password, JWT)
- Add authentication modal in UI with login/register tabs
- Create user profile screen showing game statistics and history
- Integrate Prisma 7 ORM with SQLite database for data persistence
- Store game results (mode, path, clicks, time) in database
- Auto-save completed games only when user is authenticated
- Separate business logic into reusable hooks (useSoloGame, useMultiGame)
- Organize UI into composable screen components (HomeScreen, SoloScreen, ProfileScreen, etc)
- Add session persistence across F5 refresh for solo and multiplayer
- Style auth modal, account button, and profile stats dashboard
2026-04-10 15:43:07 +02:00

103 lines
3.1 KiB
TypeScript

"use client";
import { useState } from "react";
import { signIn } from "next-auth/react";
type Mode = "login" | "register";
export function AuthModal({ onClose, onSuccess }: { onClose: () => void; onSuccess: () => void }) {
const [mode, setMode] = useState<Mode>("login");
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError(null);
setLoading(true);
try {
if (mode === "register") {
const res = await fetch("/api/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, email, password }),
});
const data = await res.json() as { error?: string };
if (!res.ok) { setError(data.error ?? "Erreur"); return; }
}
const result = await signIn("credentials", {
email, password, redirect: false,
});
if (result?.error) { setError("Email ou mot de passe incorrect"); return; }
onSuccess();
} finally {
setLoading(false);
}
}
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-box" onClick={(e) => e.stopPropagation()}>
<div className="modal-tabs">
<button
className={`modal-tab ${mode === "login" ? "active" : ""}`}
onClick={() => { setMode("login"); setError(null); }}
>
Connexion
</button>
<button
className={`modal-tab ${mode === "register" ? "active" : ""}`}
onClick={() => { setMode("register"); setError(null); }}
>
Inscription
</button>
</div>
<form className="modal-form" onSubmit={handleSubmit}>
{mode === "register" && (
<input
className="input"
type="text"
placeholder="Pseudo"
value={name}
onChange={(e) => setName(e.target.value)}
required
maxLength={30}
/>
)}
<input
className="input"
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
className="input"
type="password"
placeholder="Mot de passe"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
minLength={6}
/>
{error && <div className="error-banner" style={{ marginBottom: 0 }}>{error}</div>}
<button className="btn btn-primary" type="submit" disabled={loading}>
{loading ? "Chargement..." : mode === "login" ? "Se connecter" : "Créer un compte"}
</button>
</form>
<button className="modal-close" onClick={onClose} aria-label="Fermer"></button>
</div>
</div>
);
}