@lastbrain/module-auth 2.0.16 → 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.build.config.d.ts.map +1 -1
- package/dist/auth.build.config.js +32 -46
- package/dist/components/AccountButton.d.ts.map +1 -1
- package/dist/components/AccountButton.js +9 -5
- package/dist/web/admin/signup-stats.d.ts.map +1 -1
- package/dist/web/admin/signup-stats.js +4 -2
- package/dist/web/admin/user-detail.d.ts.map +1 -1
- package/dist/web/admin/user-detail.js +42 -17
- package/dist/web/admin/users-by-signup-source.d.ts.map +1 -1
- package/dist/web/admin/users-by-signup-source.js +18 -7
- package/dist/web/admin/users.d.ts.map +1 -1
- package/dist/web/admin/users.js +11 -6
- package/dist/web/auth/dashboard.d.ts.map +1 -1
- package/dist/web/auth/dashboard.js +7 -3
- package/dist/web/auth/folder.d.ts.map +1 -1
- package/dist/web/auth/folder.js +5 -3
- package/dist/web/auth/profile.d.ts.map +1 -1
- package/dist/web/auth/profile.js +13 -6
- package/dist/web/auth/reglage.d.ts.map +1 -1
- package/dist/web/auth/reglage.js +11 -6
- package/dist/web/public/SignInPage.d.ts.map +1 -1
- package/dist/web/public/SignInPage.js +14 -56
- package/dist/web/public/SignUpPage.d.ts.map +1 -1
- package/dist/web/public/SignUpPage.js +18 -11
- package/package.json +4 -3
- package/src/auth.build.config.ts +33 -47
- package/src/components/AccountButton.tsx +17 -10
- package/src/i18n/en.json +263 -0
- package/src/i18n/fr.json +261 -0
- package/src/web/admin/signup-stats.tsx +10 -3
- package/src/web/admin/user-detail.tsx +135 -56
- package/src/web/admin/users-by-signup-source.tsx +60 -21
- package/src/web/admin/users.tsx +41 -18
- package/src/web/auth/dashboard.tsx +25 -9
- package/src/web/auth/folder.tsx +11 -3
- package/src/web/auth/profile.tsx +63 -29
- package/src/web/auth/reglage.tsx +43 -19
- package/src/web/public/SignInPage.tsx +32 -70
- package/src/web/public/SignUpPage.tsx +48 -26
|
@@ -13,17 +13,22 @@ import {
|
|
|
13
13
|
Link,
|
|
14
14
|
} from "@lastbrain/ui";
|
|
15
15
|
import { ArrowRight, Lock, Mail, Sparkles } from "lucide-react";
|
|
16
|
-
import {
|
|
16
|
+
import { useSearchParams } from "next/navigation";
|
|
17
|
+
import { useModuleTranslation } from "@lastbrain/core";
|
|
18
|
+
import { useLocalizedRouter } from "@lastbrain/core";
|
|
17
19
|
|
|
18
20
|
function SignInForm() {
|
|
19
21
|
const searchParams = useSearchParams();
|
|
22
|
+
const t = useModuleTranslation("auth");
|
|
23
|
+
|
|
24
|
+
const router = useLocalizedRouter();
|
|
20
25
|
|
|
21
26
|
const [email, setEmail] = useState("");
|
|
22
27
|
const [password, setPassword] = useState("");
|
|
23
28
|
const [isLoading, setIsLoading] = useState(false);
|
|
24
29
|
const [error, _setError] = useState<string | null>(null);
|
|
25
30
|
const redirectUrl = searchParams.get("redirect");
|
|
26
|
-
|
|
31
|
+
|
|
27
32
|
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
28
33
|
event.preventDefault();
|
|
29
34
|
setIsLoading(true);
|
|
@@ -38,7 +43,7 @@ function SignInForm() {
|
|
|
38
43
|
if (error) {
|
|
39
44
|
addToast({
|
|
40
45
|
color: "danger",
|
|
41
|
-
title: "Erreur de connexion",
|
|
46
|
+
title: t("signin.error_title") || "Erreur de connexion",
|
|
42
47
|
description: error.message,
|
|
43
48
|
});
|
|
44
49
|
setIsLoading(false);
|
|
@@ -46,71 +51,23 @@ function SignInForm() {
|
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
setIsLoading(false);
|
|
49
|
-
|
|
54
|
+
|
|
50
55
|
addToast({
|
|
51
56
|
color: "success",
|
|
52
|
-
title: "Connecté avec succès !",
|
|
53
|
-
description:
|
|
57
|
+
title: t("signin.success_title") || "Connecté avec succès !",
|
|
58
|
+
description: `${t("signin.success_welcome") || "Bienvenue"} ${data.user?.email}`,
|
|
54
59
|
});
|
|
55
60
|
router.push(redirectUrl || "/auth/dashboard");
|
|
56
61
|
} catch (err) {
|
|
57
62
|
setIsLoading(false);
|
|
58
63
|
addToast({
|
|
59
64
|
color: "danger",
|
|
60
|
-
title: "Erreur de connexion",
|
|
65
|
+
title: t("signin.error_title") || "Erreur de connexion",
|
|
61
66
|
description: `${err instanceof Error ? err.message : String(err)}`,
|
|
62
67
|
});
|
|
63
68
|
}
|
|
64
69
|
};
|
|
65
70
|
|
|
66
|
-
// return (
|
|
67
|
-
// <div className=" min-h-screen h-full flex flex-col justify-center items-center p-4">
|
|
68
|
-
// <Card className="w-full max-w-md">
|
|
69
|
-
// <CardHeader className="flex flex-col">
|
|
70
|
-
// <h1 className="text-2xl font-semibold text-slate-900 dark:text-white">
|
|
71
|
-
// Connexion
|
|
72
|
-
// </h1>
|
|
73
|
-
// <p className="mt-1 text-sm text-slate-500">
|
|
74
|
-
// Utilisez votre adresse email pour vous connecter.
|
|
75
|
-
// </p>
|
|
76
|
-
// </CardHeader>
|
|
77
|
-
// <CardBody>
|
|
78
|
-
// <form onSubmit={handleSubmit}>
|
|
79
|
-
// <div className="space-y-6">
|
|
80
|
-
// <Input
|
|
81
|
-
// label="Email"
|
|
82
|
-
// type="email"
|
|
83
|
-
// className="mb-6"
|
|
84
|
-
// required
|
|
85
|
-
// value={email}
|
|
86
|
-
// onChange={(event) => setEmail(event.target.value)}
|
|
87
|
-
// />
|
|
88
|
-
|
|
89
|
-
// <Input
|
|
90
|
-
// label="Mot de passe"
|
|
91
|
-
// type="password"
|
|
92
|
-
// required
|
|
93
|
-
// placeholder="Password"
|
|
94
|
-
// className="mb-6"
|
|
95
|
-
// value={password}
|
|
96
|
-
// onChange={(event) => setPassword(event.target.value)}
|
|
97
|
-
// />
|
|
98
|
-
|
|
99
|
-
// <Button
|
|
100
|
-
// size="lg"
|
|
101
|
-
// type="submit"
|
|
102
|
-
// className="w-full"
|
|
103
|
-
// isLoading={isLoading}
|
|
104
|
-
// >
|
|
105
|
-
// Se connecter
|
|
106
|
-
// </Button>
|
|
107
|
-
// </div>
|
|
108
|
-
// </form>
|
|
109
|
-
// </CardBody>
|
|
110
|
-
// </Card>
|
|
111
|
-
// </div>
|
|
112
|
-
// );
|
|
113
|
-
|
|
114
71
|
return (
|
|
115
72
|
<div className="relative min-h-screen w-full overflow-hidden bg-gradient-to-br from-primary-50/30 to-secondary-50/30 dark:from-primary-950/50 dark:to-secondary-950/50">
|
|
116
73
|
{/* Background decoration */}
|
|
@@ -126,15 +83,16 @@ function SignInForm() {
|
|
|
126
83
|
startContent={<Sparkles className="w-4 h-4" />}
|
|
127
84
|
className="mb-4 p-2"
|
|
128
85
|
>
|
|
129
|
-
Espace membre
|
|
86
|
+
{t("signin.chip_label") || "Espace membre"}
|
|
130
87
|
</Chip>
|
|
131
88
|
<h1 className="mb-3 text-4xl font-bold">
|
|
132
89
|
<span className="bg-gradient-to-r from-primary-600 to-secondary-600 bg-clip-text text-transparent">
|
|
133
|
-
Bon retour
|
|
90
|
+
{t("signin.title") || "Bon retour"}
|
|
134
91
|
</span>
|
|
135
92
|
</h1>
|
|
136
|
-
<p className="text-default-600 dark:text-default-
|
|
137
|
-
|
|
93
|
+
<p className="text-default-600 dark:text-default-700">
|
|
94
|
+
{t("signin.subtitle") ||
|
|
95
|
+
"Connectez-vous pour accéder à votre espace"}
|
|
138
96
|
</p>
|
|
139
97
|
</div>
|
|
140
98
|
|
|
@@ -143,9 +101,11 @@ function SignInForm() {
|
|
|
143
101
|
<CardBody className="gap-6 p-8">
|
|
144
102
|
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
|
|
145
103
|
<Input
|
|
146
|
-
label="Email"
|
|
104
|
+
label={t("email") || "Email"}
|
|
147
105
|
type="email"
|
|
148
|
-
placeholder=
|
|
106
|
+
placeholder={
|
|
107
|
+
t("signin.email_placeholder") || "votre@email.com"
|
|
108
|
+
}
|
|
149
109
|
value={email}
|
|
150
110
|
onChange={(e) => setEmail(e.target.value)}
|
|
151
111
|
required
|
|
@@ -159,7 +119,7 @@ function SignInForm() {
|
|
|
159
119
|
|
|
160
120
|
<div className="flex flex-col gap-2">
|
|
161
121
|
<Input
|
|
162
|
-
label="Mot de passe"
|
|
122
|
+
label={t("password") || "Mot de passe"}
|
|
163
123
|
type="password"
|
|
164
124
|
placeholder="••••••••"
|
|
165
125
|
value={password}
|
|
@@ -177,7 +137,7 @@ function SignInForm() {
|
|
|
177
137
|
href="/forgot-password"
|
|
178
138
|
className="text-xs text-default-500 hover:text-primary-500 self-end"
|
|
179
139
|
>
|
|
180
|
-
Mot de passe oublié ?
|
|
140
|
+
{t("signin.forgot_password") || "Mot de passe oublié ?"}
|
|
181
141
|
</Link>
|
|
182
142
|
</div>
|
|
183
143
|
|
|
@@ -199,21 +159,23 @@ function SignInForm() {
|
|
|
199
159
|
}
|
|
200
160
|
isLoading={isLoading}
|
|
201
161
|
>
|
|
202
|
-
Se connecter
|
|
162
|
+
{t("signin.submit") || "Se connecter"}
|
|
203
163
|
</Button>
|
|
204
164
|
</form>
|
|
205
165
|
|
|
206
166
|
{/* Divider */}
|
|
207
167
|
<div className="relative flex items-center gap-4 py-2">
|
|
208
168
|
<div className="h-px flex-1 bg-default-200" />
|
|
209
|
-
<span className="text-xs text-default-400">
|
|
169
|
+
<span className="text-xs text-default-400">
|
|
170
|
+
{t("or") || "OU"}
|
|
171
|
+
</span>
|
|
210
172
|
<div className="h-px flex-1 bg-default-200" />
|
|
211
173
|
</div>
|
|
212
174
|
|
|
213
175
|
{/* Sign up link */}
|
|
214
176
|
<div className="text-center">
|
|
215
177
|
<p className="text-sm text-default-600">
|
|
216
|
-
Pas encore de compte ?{" "}
|
|
178
|
+
{t("signin.no_account") || "Pas encore de compte ?"}{" "}
|
|
217
179
|
<Link
|
|
218
180
|
href={
|
|
219
181
|
redirectUrl
|
|
@@ -222,7 +184,7 @@ function SignInForm() {
|
|
|
222
184
|
}
|
|
223
185
|
className="font-semibold text-primary-600 hover:text-primary-700"
|
|
224
186
|
>
|
|
225
|
-
Créer un compte
|
|
187
|
+
{t("signin.sign_up") || "Créer un compte"}
|
|
226
188
|
</Link>
|
|
227
189
|
</p>
|
|
228
190
|
</div>
|
|
@@ -230,13 +192,13 @@ function SignInForm() {
|
|
|
230
192
|
</Card>
|
|
231
193
|
|
|
232
194
|
{/* Footer */}
|
|
233
|
-
<p className="mt-8 text-center text-
|
|
234
|
-
|
|
195
|
+
<p className="mt-8 text-center text-sm text-default-700">
|
|
196
|
+
{t("signin.accept_terms")}{" "}
|
|
235
197
|
<Link
|
|
236
198
|
href="/legal/terms"
|
|
237
199
|
className="underline hover:text-primary-500"
|
|
238
200
|
>
|
|
239
|
-
|
|
201
|
+
{t("signin.term")}
|
|
240
202
|
</Link>
|
|
241
203
|
</p>
|
|
242
204
|
</div>
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Chip,
|
|
10
10
|
addToast,
|
|
11
11
|
} from "@lastbrain/ui";
|
|
12
|
-
import {
|
|
12
|
+
import { useSearchParams } from "next/navigation";
|
|
13
13
|
import { Suspense, useState } from "react";
|
|
14
14
|
import {
|
|
15
15
|
Mail,
|
|
@@ -19,11 +19,14 @@ import {
|
|
|
19
19
|
Sparkles,
|
|
20
20
|
CheckCircle2,
|
|
21
21
|
} from "lucide-react";
|
|
22
|
-
import {
|
|
22
|
+
import { useModuleTranslation } from "@lastbrain/core";
|
|
23
|
+
import { useLocalizedRouter } from "@lastbrain/core";
|
|
23
24
|
|
|
24
25
|
function SignUpForm() {
|
|
25
|
-
const router =
|
|
26
|
+
const router = useLocalizedRouter();
|
|
26
27
|
const searchParams = useSearchParams();
|
|
28
|
+
|
|
29
|
+
const t = useModuleTranslation("auth");
|
|
27
30
|
const [fullName, setFullName] = useState("");
|
|
28
31
|
const [email, setEmail] = useState("");
|
|
29
32
|
const [password, setPassword] = useState("");
|
|
@@ -41,12 +44,18 @@ function SignUpForm() {
|
|
|
41
44
|
setSuccess(null);
|
|
42
45
|
|
|
43
46
|
if (password !== confirmPassword) {
|
|
44
|
-
setError(
|
|
47
|
+
setError(
|
|
48
|
+
t("signup.password_mismatch") ||
|
|
49
|
+
"Les mots de passe ne correspondent pas."
|
|
50
|
+
);
|
|
45
51
|
return;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
if (password.length < 6) {
|
|
49
|
-
setError(
|
|
55
|
+
setError(
|
|
56
|
+
t("signup.password_too_short") ||
|
|
57
|
+
"Le mot de passe doit contenir au moins 6 caractères."
|
|
58
|
+
);
|
|
50
59
|
return;
|
|
51
60
|
}
|
|
52
61
|
|
|
@@ -86,7 +95,7 @@ function SignUpForm() {
|
|
|
86
95
|
if (redirectUrl) {
|
|
87
96
|
router.push(`/signin?redirect=${encodeURIComponent(redirectUrl)}`);
|
|
88
97
|
} else {
|
|
89
|
-
router.push(
|
|
98
|
+
router.push(`/signin`);
|
|
90
99
|
}
|
|
91
100
|
}, 2000);
|
|
92
101
|
} catch {
|
|
@@ -115,15 +124,16 @@ function SignUpForm() {
|
|
|
115
124
|
startContent={<Sparkles className="w-4 h-4" />}
|
|
116
125
|
className="mb-4 p-2"
|
|
117
126
|
>
|
|
118
|
-
Rejoignez-nous
|
|
127
|
+
{t("signup.chip_label") || "Rejoignez-nous"}
|
|
119
128
|
</Chip>
|
|
120
129
|
<h1 className="mb-3 text-4xl font-bold">
|
|
121
130
|
<span className="bg-gradient-to-r from-secondary-600 to-primary-600 bg-clip-text text-transparent">
|
|
122
|
-
Commencer gratuitement
|
|
131
|
+
{t("signup.title") || "Commencer gratuitement"}
|
|
123
132
|
</span>
|
|
124
133
|
</h1>
|
|
125
|
-
<p className="text-default-600 dark:text-default-
|
|
126
|
-
|
|
134
|
+
<p className="text-default-600 dark:text-default-700">
|
|
135
|
+
{t("signup.subtitle") ||
|
|
136
|
+
"Créez votre compte en quelques secondes"}
|
|
127
137
|
</p>
|
|
128
138
|
</div>
|
|
129
139
|
|
|
@@ -132,9 +142,11 @@ function SignUpForm() {
|
|
|
132
142
|
<CardBody className="gap-6 p-8">
|
|
133
143
|
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
|
|
134
144
|
<Input
|
|
135
|
-
label="Nom complet"
|
|
145
|
+
label={t("signup.full_name") || "Nom complet"}
|
|
136
146
|
type="text"
|
|
137
|
-
placeholder=
|
|
147
|
+
placeholder={
|
|
148
|
+
t("signup.full_name_placeholder") || "Jean Dupont"
|
|
149
|
+
}
|
|
138
150
|
value={fullName}
|
|
139
151
|
onChange={(e) => setFullName(e.target.value)}
|
|
140
152
|
startContent={<User className="h-4 w-4 text-default-400" />}
|
|
@@ -146,9 +158,11 @@ function SignUpForm() {
|
|
|
146
158
|
/>
|
|
147
159
|
|
|
148
160
|
<Input
|
|
149
|
-
label="Email"
|
|
161
|
+
label={t("email") || "Email"}
|
|
150
162
|
type="email"
|
|
151
|
-
placeholder=
|
|
163
|
+
placeholder={
|
|
164
|
+
t("signin.email_placeholder") || "votre@email.com"
|
|
165
|
+
}
|
|
152
166
|
value={email}
|
|
153
167
|
onChange={(e) => setEmail(e.target.value)}
|
|
154
168
|
required
|
|
@@ -161,7 +175,7 @@ function SignUpForm() {
|
|
|
161
175
|
/>
|
|
162
176
|
|
|
163
177
|
<Input
|
|
164
|
-
label="Mot de passe"
|
|
178
|
+
label={t("password") || "Mot de passe"}
|
|
165
179
|
type="password"
|
|
166
180
|
placeholder="••••••••"
|
|
167
181
|
value={password}
|
|
@@ -174,11 +188,15 @@ function SignUpForm() {
|
|
|
174
188
|
inputWrapper:
|
|
175
189
|
"border border-default-200/60 hover:border-secondary-400 focus-within:border-secondary-500",
|
|
176
190
|
}}
|
|
177
|
-
description=
|
|
191
|
+
description={
|
|
192
|
+
t("signup.password_hint") || "Minimum 6 caractères"
|
|
193
|
+
}
|
|
178
194
|
/>
|
|
179
195
|
|
|
180
196
|
<Input
|
|
181
|
-
label=
|
|
197
|
+
label={
|
|
198
|
+
t("signup.confirm_password") || "Confirmer le mot de passe"
|
|
199
|
+
}
|
|
182
200
|
type="password"
|
|
183
201
|
placeholder="••••••••"
|
|
184
202
|
value={confirmPassword}
|
|
@@ -222,21 +240,23 @@ function SignUpForm() {
|
|
|
222
240
|
}
|
|
223
241
|
isLoading={loading}
|
|
224
242
|
>
|
|
225
|
-
Créer mon compte
|
|
243
|
+
{t("signup.submit") || "Créer mon compte"}
|
|
226
244
|
</Button>
|
|
227
245
|
</form>
|
|
228
246
|
|
|
229
247
|
{/* Divider */}
|
|
230
248
|
<div className="relative flex items-center gap-4 py-2">
|
|
231
249
|
<div className="h-px flex-1 bg-default-200" />
|
|
232
|
-
<span className="text-xs text-default-400">
|
|
250
|
+
<span className="text-xs text-default-400">
|
|
251
|
+
{t("signup.or") || "OU"}
|
|
252
|
+
</span>
|
|
233
253
|
<div className="h-px flex-1 bg-default-200" />
|
|
234
254
|
</div>
|
|
235
255
|
|
|
236
256
|
{/* Sign in link */}
|
|
237
257
|
<div className="text-center">
|
|
238
258
|
<p className="text-sm text-default-600">
|
|
239
|
-
Déjà inscrit ?{" "}
|
|
259
|
+
{t("signup.have_account") || "Déjà inscrit ?"}{" "}
|
|
240
260
|
<Link
|
|
241
261
|
href={
|
|
242
262
|
redirectUrl
|
|
@@ -245,7 +265,7 @@ function SignUpForm() {
|
|
|
245
265
|
}
|
|
246
266
|
className="font-semibold text-secondary-600 hover:text-secondary-700"
|
|
247
267
|
>
|
|
248
|
-
Se connecter
|
|
268
|
+
{t("signin.submit") || "Se connecter"}
|
|
249
269
|
</Link>
|
|
250
270
|
</p>
|
|
251
271
|
</div>
|
|
@@ -253,20 +273,22 @@ function SignUpForm() {
|
|
|
253
273
|
</Card>
|
|
254
274
|
|
|
255
275
|
{/* Footer */}
|
|
256
|
-
|
|
257
|
-
|
|
276
|
+
|
|
277
|
+
<p className="mt-8 text-center text-sm text-default-700">
|
|
278
|
+
{t("signup.legal_prefix") ||
|
|
279
|
+
"En créant un compte, vous acceptez nos"}{" "}
|
|
258
280
|
<Link
|
|
259
281
|
href="/legal/terms"
|
|
260
282
|
className="underline hover:text-secondary-500"
|
|
261
283
|
>
|
|
262
|
-
conditions d'utilisation
|
|
284
|
+
{t("signup.terms") || "conditions d'utilisation"}
|
|
263
285
|
</Link>{" "}
|
|
264
|
-
et notre{" "}
|
|
286
|
+
{t("signup.legal_and") || "et notre"}{" "}
|
|
265
287
|
<Link
|
|
266
288
|
href="/legal/privacy"
|
|
267
289
|
className="underline hover:text-secondary-500"
|
|
268
290
|
>
|
|
269
|
-
politique de confidentialité
|
|
291
|
+
{t("signup.privacy") || "politique de confidentialité"}
|
|
270
292
|
</Link>
|
|
271
293
|
</p>
|
|
272
294
|
</div>
|