Update Dockerfile and package.json to use Prisma migrations, add bcryptjs and next-auth dependencies, and enhance README instructions for database setup. Refactor Prisma schema to include password hashing for users and implement evaluation sharing functionality. Improve admin page with user management features and integrate session handling for authentication. Enhance evaluation detail page with sharing options and update API routes for access control based on user roles.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m4s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m4s
This commit is contained in:
85
src/app/auth/login/page.tsx
Normal file
85
src/app/auth/login/page.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { signIn } from "next-auth/react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function LoginPage() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
setError("");
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await signIn("credentials", {
|
||||
email,
|
||||
password,
|
||||
redirect: false,
|
||||
});
|
||||
if (res?.error) {
|
||||
setError("Email ou mot de passe incorrect");
|
||||
return;
|
||||
}
|
||||
window.location.href = "/";
|
||||
} catch {
|
||||
setError("Erreur de connexion");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-sm">
|
||||
<h1 className="mb-6 font-mono text-lg font-medium text-zinc-800 dark:text-zinc-100">
|
||||
Connexion
|
||||
</h1>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label className="mb-1 block font-mono text-xs text-zinc-600 dark:text-zinc-400">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
className="w-full rounded border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500/30"
|
||||
placeholder="vous@example.com"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="mb-1 block font-mono text-xs text-zinc-600 dark:text-zinc-400">
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
className="w-full rounded border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500/30"
|
||||
/>
|
||||
</div>
|
||||
{error && (
|
||||
<p className="font-mono text-xs text-red-500">{error}</p>
|
||||
)}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full rounded border border-cyan-500/50 bg-cyan-500/10 px-3 py-2 font-mono text-sm text-cyan-600 dark:text-cyan-400 hover:bg-cyan-500/20 disabled:opacity-50"
|
||||
>
|
||||
{loading ? "..." : "Se connecter"}
|
||||
</button>
|
||||
</form>
|
||||
<p className="mt-4 font-mono text-xs text-zinc-500 dark:text-zinc-400">
|
||||
Pas de compte ?{" "}
|
||||
<Link href="/auth/signup" className="text-cyan-600 dark:text-cyan-400 hover:underline">
|
||||
S'inscrire
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user