@lastbrain/module-auth 2.0.16 → 2.0.27
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 +42 -51
- package/dist/components/AccountButton.d.ts.map +1 -1
- package/dist/components/AccountButton.js +9 -5
- package/dist/components/auth/dashboard.d.ts +2 -0
- package/dist/components/auth/dashboard.d.ts.map +1 -0
- package/dist/components/auth/dashboard.js +47 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- 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 +43 -52
- package/src/components/AccountButton.tsx +17 -10
- package/src/{web → components}/auth/dashboard.tsx +33 -14
- package/src/i18n/en.json +265 -0
- package/src/i18n/fr.json +262 -0
- package/src/index.ts +1 -1
- 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/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
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Button, Card, CardBody, Input, Link, Chip, addToast, } from "@lastbrain/ui";
|
|
4
|
-
import {
|
|
4
|
+
import { useSearchParams } from "next/navigation";
|
|
5
5
|
import { Suspense, useState } from "react";
|
|
6
6
|
import { Mail, Lock, User, ArrowRight, Sparkles, CheckCircle2, } from "lucide-react";
|
|
7
|
+
import { useModuleTranslation } from "@lastbrain/core";
|
|
8
|
+
import { useLocalizedRouter } from "@lastbrain/core";
|
|
7
9
|
function SignUpForm() {
|
|
8
|
-
const router =
|
|
10
|
+
const router = useLocalizedRouter();
|
|
9
11
|
const searchParams = useSearchParams();
|
|
12
|
+
const t = useModuleTranslation("auth");
|
|
10
13
|
const [fullName, setFullName] = useState("");
|
|
11
14
|
const [email, setEmail] = useState("");
|
|
12
15
|
const [password, setPassword] = useState("");
|
|
@@ -21,11 +24,13 @@ function SignUpForm() {
|
|
|
21
24
|
setError(null);
|
|
22
25
|
setSuccess(null);
|
|
23
26
|
if (password !== confirmPassword) {
|
|
24
|
-
setError("
|
|
27
|
+
setError(t("signup.password_mismatch") ||
|
|
28
|
+
"Les mots de passe ne correspondent pas.");
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
27
31
|
if (password.length < 6) {
|
|
28
|
-
setError("
|
|
32
|
+
setError(t("signup.password_too_short") ||
|
|
33
|
+
"Le mot de passe doit contenir au moins 6 caractères.");
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
setLoading(true);
|
|
@@ -58,7 +63,7 @@ function SignUpForm() {
|
|
|
58
63
|
router.push(`/signin?redirect=${encodeURIComponent(redirectUrl)}`);
|
|
59
64
|
}
|
|
60
65
|
else {
|
|
61
|
-
router.push(
|
|
66
|
+
router.push(`/signin`);
|
|
62
67
|
}
|
|
63
68
|
}, 2000);
|
|
64
69
|
}
|
|
@@ -73,21 +78,23 @@ function SignUpForm() {
|
|
|
73
78
|
setLoading(false);
|
|
74
79
|
}
|
|
75
80
|
};
|
|
76
|
-
return (_jsxs("div", { className: " relative min-h-screen w-full overflow-hidden bg-gradient-to-br from-secondary-50/30 to-primary-50/30 dark:from-secondary-950/50 dark:to-primary-950/50", children: [_jsx("div", { className: "absolute inset-0 bg-grid-slate-100 dark:bg-grid-slate-800/20 mask-[linear-gradient(0deg,white,rgba(255,255,255,0.6))] dark:mask-[linear-gradient(0deg,rgba(255,255,255,0.1),rgba(255,255,255,0.05))]" }), _jsx("div", { className: "relative flex min-h-screen items-center justify-center px-4 py-12", children: _jsxs("div", { className: "w-full max-w-md", children: [_jsxs("div", { className: "mb-8 text-center", children: [_jsx(Chip, { color: "secondary", variant: "flat", startContent: _jsx(Sparkles, { className: "w-4 h-4" }), className: "mb-4 p-2", children: "Rejoignez-nous" }), _jsx("h1", { className: "mb-3 text-4xl font-bold", children: _jsx("span", { className: "bg-gradient-to-r from-secondary-600 to-primary-600 bg-clip-text text-transparent", children: "Commencer gratuitement" }) }), _jsx("p", { className: "text-default-600 dark:text-default-
|
|
81
|
+
return (_jsxs("div", { className: " relative min-h-screen w-full overflow-hidden bg-gradient-to-br from-secondary-50/30 to-primary-50/30 dark:from-secondary-950/50 dark:to-primary-950/50", children: [_jsx("div", { className: "absolute inset-0 bg-grid-slate-100 dark:bg-grid-slate-800/20 mask-[linear-gradient(0deg,white,rgba(255,255,255,0.6))] dark:mask-[linear-gradient(0deg,rgba(255,255,255,0.1),rgba(255,255,255,0.05))]" }), _jsx("div", { className: "relative flex min-h-screen items-center justify-center px-4 py-12", children: _jsxs("div", { className: "w-full max-w-md", children: [_jsxs("div", { className: "mb-8 text-center", children: [_jsx(Chip, { color: "secondary", variant: "flat", startContent: _jsx(Sparkles, { className: "w-4 h-4" }), className: "mb-4 p-2", children: t("signup.chip_label") || "Rejoignez-nous" }), _jsx("h1", { className: "mb-3 text-4xl font-bold", children: _jsx("span", { className: "bg-gradient-to-r from-secondary-600 to-primary-600 bg-clip-text text-transparent", children: t("signup.title") || "Commencer gratuitement" }) }), _jsx("p", { className: "text-default-600 dark:text-default-700", children: t("signup.subtitle") ||
|
|
82
|
+
"Créez votre compte en quelques secondes" })] }), _jsx(Card, { className: "border border-default-200/60 bg-background/60 backdrop-blur-md backdrop-saturate-150 shadow-xl", children: _jsxs(CardBody, { className: "gap-6 p-8", children: [_jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-6", children: [_jsx(Input, { label: t("signup.full_name") || "Nom complet", type: "text", placeholder: t("signup.full_name_placeholder") || "Jean Dupont", value: fullName, onChange: (e) => setFullName(e.target.value), startContent: _jsx(User, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
77
83
|
input: "text-base",
|
|
78
84
|
inputWrapper: "border border-default-200/60 hover:border-secondary-400 focus-within:border-secondary-500",
|
|
79
|
-
} }), _jsx(Input, { label: "Email", type: "email", placeholder: "votre@email.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, startContent: _jsx(Mail, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
85
|
+
} }), _jsx(Input, { label: t("email") || "Email", type: "email", placeholder: t("signin.email_placeholder") || "votre@email.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, startContent: _jsx(Mail, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
80
86
|
input: "text-base",
|
|
81
87
|
inputWrapper: "border border-default-200/60 hover:border-secondary-400 focus-within:border-secondary-500",
|
|
82
|
-
} }), _jsx(Input, { label: "Mot de passe", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChange: (e) => setPassword(e.target.value), required: true, minLength: 6, startContent: _jsx(Lock, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
88
|
+
} }), _jsx(Input, { label: t("password") || "Mot de passe", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChange: (e) => setPassword(e.target.value), required: true, minLength: 6, startContent: _jsx(Lock, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
83
89
|
input: "text-base",
|
|
84
90
|
inputWrapper: "border border-default-200/60 hover:border-secondary-400 focus-within:border-secondary-500",
|
|
85
|
-
}, description: "Minimum 6
|
|
91
|
+
}, description: t("signup.password_hint") || "Minimum 6 caractères" }), _jsx(Input, { label: t("signup.confirm_password") || "Confirmer le mot de passe", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), required: true, minLength: 6, startContent: _jsx(Lock, { className: "h-4 w-4 text-default-400" }), classNames: {
|
|
86
92
|
input: "text-base",
|
|
87
93
|
inputWrapper: "border border-default-200/60 hover:border-secondary-400 focus-within:border-secondary-500",
|
|
88
|
-
} }), error && (_jsx("div", { className: "rounded-lg border border-danger-200 bg-danger-50/50 px-4 py-3 dark:border-danger-800 dark:bg-danger-950/50", children: _jsx("p", { className: "text-sm text-danger-600 dark:text-danger-400", children: error }) })), success && (_jsx("div", { className: "rounded-lg border border-success-200 bg-success-50/50 px-4 py-3 dark:border-success-800 dark:bg-success-950/50", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-success-600 dark:text-success-400" }), _jsx("p", { className: "text-sm text-success-600 dark:text-success-400", children: success })] }) })), _jsx(Button, { type: "submit", color: "secondary", size: "lg", className: "w-full font-semibold", endContent: loading ? null : _jsx(ArrowRight, { className: "h-5 w-5" }), isLoading: loading, children: "
|
|
94
|
+
} }), error && (_jsx("div", { className: "rounded-lg border border-danger-200 bg-danger-50/50 px-4 py-3 dark:border-danger-800 dark:bg-danger-950/50", children: _jsx("p", { className: "text-sm text-danger-600 dark:text-danger-400", children: error }) })), success && (_jsx("div", { className: "rounded-lg border border-success-200 bg-success-50/50 px-4 py-3 dark:border-success-800 dark:bg-success-950/50", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-success-600 dark:text-success-400" }), _jsx("p", { className: "text-sm text-success-600 dark:text-success-400", children: success })] }) })), _jsx(Button, { type: "submit", color: "secondary", size: "lg", className: "w-full font-semibold", endContent: loading ? null : _jsx(ArrowRight, { className: "h-5 w-5" }), isLoading: loading, children: t("signup.submit") || "Créer mon compte" })] }), _jsxs("div", { className: "relative flex items-center gap-4 py-2", children: [_jsx("div", { className: "h-px flex-1 bg-default-200" }), _jsx("span", { className: "text-xs text-default-400", children: t("signup.or") || "OU" }), _jsx("div", { className: "h-px flex-1 bg-default-200" })] }), _jsx("div", { className: "text-center", children: _jsxs("p", { className: "text-sm text-default-600", children: [t("signup.have_account") || "Déjà inscrit ?", " ", _jsx(Link, { href: redirectUrl
|
|
89
95
|
? `/signin?redirect=${encodeURIComponent(redirectUrl)}`
|
|
90
|
-
: "/signin", className: "font-semibold text-secondary-600 hover:text-secondary-700", children: "Se connecter" })] }) })] }) }), _jsxs("p", { className: "mt-8 text-center text-
|
|
96
|
+
: "/signin", className: "font-semibold text-secondary-600 hover:text-secondary-700", children: t("signin.submit") || "Se connecter" })] }) })] }) }), _jsxs("p", { className: "mt-8 text-center text-sm text-default-700", children: [t("signup.legal_prefix") ||
|
|
97
|
+
"En créant un compte, vous acceptez nos", " ", _jsx(Link, { href: "/legal/terms", className: "underline hover:text-secondary-500", children: t("signup.terms") || "conditions d'utilisation" }), " ", t("signup.legal_and") || "et notre", " ", _jsx(Link, { href: "/legal/privacy", className: "underline hover:text-secondary-500", children: t("signup.privacy") || "politique de confidentialité" })] })] }) })] }));
|
|
91
98
|
}
|
|
92
99
|
export function SignUpPage() {
|
|
93
100
|
return (_jsx(Suspense, { fallback: _jsx("div", { children: "Chargement..." }), children: _jsx(SignUpForm, {}) }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/module-auth",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
4
4
|
"description": "Module d'authentification complet pour LastBrain avec Supabase",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -32,8 +32,9 @@
|
|
|
32
32
|
"supabase"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@lastbrain/
|
|
36
|
-
"@lastbrain/
|
|
35
|
+
"@lastbrain/app": "^2.0.31",
|
|
36
|
+
"@lastbrain/core": "^2.0.27",
|
|
37
|
+
"@lastbrain/ui": "^2.0.27",
|
|
37
38
|
"@supabase/supabase-js": "^2.86.0",
|
|
38
39
|
"lucide-react": "^0.554.0",
|
|
39
40
|
"react": "^19.2.1",
|
package/src/auth.build.config.ts
CHANGED
|
@@ -18,11 +18,6 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
18
18
|
path: "/reset-password",
|
|
19
19
|
componentExport: "ResetPassword",
|
|
20
20
|
},
|
|
21
|
-
{
|
|
22
|
-
section: "auth",
|
|
23
|
-
path: "/dashboard",
|
|
24
|
-
componentExport: "DashboardPage",
|
|
25
|
-
},
|
|
26
21
|
{
|
|
27
22
|
section: "auth",
|
|
28
23
|
path: "/folder",
|
|
@@ -141,8 +136,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
141
136
|
menu: {
|
|
142
137
|
public: [
|
|
143
138
|
{
|
|
144
|
-
title: "
|
|
145
|
-
description: "
|
|
139
|
+
title: "module-auth.menu.notifications",
|
|
140
|
+
description: "module-auth.menu.notifications_desc",
|
|
146
141
|
icon: "Bell",
|
|
147
142
|
path: "#",
|
|
148
143
|
order: 998,
|
|
@@ -151,8 +146,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
151
146
|
componentExport: "NotificationButton",
|
|
152
147
|
},
|
|
153
148
|
{
|
|
154
|
-
title: "
|
|
155
|
-
description: "
|
|
149
|
+
title: "module-auth.menu.account",
|
|
150
|
+
description: "module-auth.menu.account_desc",
|
|
156
151
|
icon: "User",
|
|
157
152
|
path: "#",
|
|
158
153
|
order: 999,
|
|
@@ -161,8 +156,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
161
156
|
componentExport: "AccountButton",
|
|
162
157
|
},
|
|
163
158
|
{
|
|
164
|
-
title: "
|
|
165
|
-
description: "
|
|
159
|
+
title: "module-auth.menu.theme",
|
|
160
|
+
description: "module-auth.menu.theme_desc",
|
|
166
161
|
icon: "Palette",
|
|
167
162
|
path: "#",
|
|
168
163
|
order: 9999,
|
|
@@ -173,8 +168,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
173
168
|
],
|
|
174
169
|
admin: [
|
|
175
170
|
{
|
|
176
|
-
title: "
|
|
177
|
-
description: "
|
|
171
|
+
title: "module-auth.menu.users_management",
|
|
172
|
+
description: "module-auth.menu.users_management_desc",
|
|
178
173
|
icon: "Users2",
|
|
179
174
|
path: "/admin/auth/users",
|
|
180
175
|
order: 1,
|
|
@@ -182,16 +177,16 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
182
177
|
shortcutDisplay: "⌘⇧U",
|
|
183
178
|
},
|
|
184
179
|
{
|
|
185
|
-
title: "
|
|
186
|
-
description: "
|
|
180
|
+
title: "module-auth.menu.signup_stats",
|
|
181
|
+
description: "module-auth.menu.signup_stats_desc",
|
|
187
182
|
icon: "UserStar",
|
|
188
183
|
path: "/admin/auth/signup-stats",
|
|
189
184
|
order: 2,
|
|
190
185
|
},
|
|
191
186
|
|
|
192
187
|
{
|
|
193
|
-
title: "
|
|
194
|
-
description: "
|
|
188
|
+
title: "module-auth.menu.notifications",
|
|
189
|
+
description: "module-auth.menu.notifications_desc",
|
|
195
190
|
icon: "Bell",
|
|
196
191
|
path: "#",
|
|
197
192
|
order: 998,
|
|
@@ -200,8 +195,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
200
195
|
componentExport: "NotificationButton",
|
|
201
196
|
},
|
|
202
197
|
{
|
|
203
|
-
title: "
|
|
204
|
-
description: "
|
|
198
|
+
title: "module-auth.menu.account",
|
|
199
|
+
description: "module-auth.menu.account_desc",
|
|
205
200
|
icon: "User",
|
|
206
201
|
path: "#",
|
|
207
202
|
order: 999,
|
|
@@ -210,8 +205,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
210
205
|
componentExport: "AccountButton",
|
|
211
206
|
},
|
|
212
207
|
{
|
|
213
|
-
title: "
|
|
214
|
-
description: "
|
|
208
|
+
title: "module-auth.menu.theme",
|
|
209
|
+
description: "module-auth.menu.theme_desc",
|
|
215
210
|
icon: "Palette",
|
|
216
211
|
path: "#",
|
|
217
212
|
order: 9999,
|
|
@@ -222,8 +217,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
222
217
|
],
|
|
223
218
|
auth: [
|
|
224
219
|
{
|
|
225
|
-
title: "
|
|
226
|
-
description: "
|
|
220
|
+
title: "module-auth.menu.dashboard",
|
|
221
|
+
description: "module-auth.menu.dashboard_desc",
|
|
227
222
|
icon: "LayoutDashboard",
|
|
228
223
|
path: "/auth/dashboard",
|
|
229
224
|
order: 1,
|
|
@@ -231,8 +226,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
231
226
|
shortcutDisplay: "⌘⇧D",
|
|
232
227
|
},
|
|
233
228
|
{
|
|
234
|
-
title: "
|
|
235
|
-
description: "
|
|
229
|
+
title: "module-auth.menu.folder",
|
|
230
|
+
description: "module-auth.menu.folder_desc",
|
|
236
231
|
icon: "FolderOpen",
|
|
237
232
|
path: "/auth/folder",
|
|
238
233
|
order: 99,
|
|
@@ -240,8 +235,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
240
235
|
shortcutDisplay: "⌘⇧F",
|
|
241
236
|
},
|
|
242
237
|
{
|
|
243
|
-
title: "
|
|
244
|
-
description: "
|
|
238
|
+
title: "module-auth.menu.notifications",
|
|
239
|
+
description: "module-auth.menu.notifications_desc",
|
|
245
240
|
icon: "Bell",
|
|
246
241
|
path: "#",
|
|
247
242
|
order: 998,
|
|
@@ -250,8 +245,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
250
245
|
componentExport: "NotificationButton",
|
|
251
246
|
},
|
|
252
247
|
{
|
|
253
|
-
title: "
|
|
254
|
-
description: "
|
|
248
|
+
title: "module-auth.menu.account",
|
|
249
|
+
description: "module-auth.menu.account_desc",
|
|
255
250
|
icon: "User",
|
|
256
251
|
path: "#",
|
|
257
252
|
order: 999,
|
|
@@ -260,8 +255,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
260
255
|
componentExport: "AccountButton",
|
|
261
256
|
},
|
|
262
257
|
{
|
|
263
|
-
title: "
|
|
264
|
-
description: "
|
|
258
|
+
title: "module-auth.menu.theme",
|
|
259
|
+
description: "module-auth.menu.theme_desc",
|
|
265
260
|
icon: "Palette",
|
|
266
261
|
path: "#",
|
|
267
262
|
order: 9999,
|
|
@@ -272,8 +267,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
272
267
|
],
|
|
273
268
|
account: [
|
|
274
269
|
{
|
|
275
|
-
title: "
|
|
276
|
-
description: "
|
|
270
|
+
title: "module-auth.menu.profile",
|
|
271
|
+
description: "module-auth.menu.profile_desc",
|
|
277
272
|
icon: "User2",
|
|
278
273
|
path: "/auth/profile",
|
|
279
274
|
order: 1,
|
|
@@ -281,8 +276,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
281
276
|
shortcutDisplay: "⌘⇧P",
|
|
282
277
|
},
|
|
283
278
|
{
|
|
284
|
-
title: "
|
|
285
|
-
description: "
|
|
279
|
+
title: "module-auth.menu.settings",
|
|
280
|
+
description: "module-auth.menu.settings_desc",
|
|
286
281
|
icon: "Settings",
|
|
287
282
|
path: "/auth/reglage",
|
|
288
283
|
order: 2,
|
|
@@ -290,8 +285,8 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
290
285
|
shortcutDisplay: "⌘⇧S",
|
|
291
286
|
},
|
|
292
287
|
{
|
|
293
|
-
title: "
|
|
294
|
-
description: "
|
|
288
|
+
title: "module-auth.menu.signout",
|
|
289
|
+
description: "module-auth.menu.signout",
|
|
295
290
|
icon: "LogOut",
|
|
296
291
|
path: "/signout",
|
|
297
292
|
order: 99,
|
|
@@ -308,22 +303,18 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
308
303
|
filter: "owner_id=eq.${USER_ID}",
|
|
309
304
|
broadcast: "user_notifications_updated",
|
|
310
305
|
},
|
|
311
|
-
{
|
|
312
|
-
schema: "public",
|
|
313
|
-
table: "user_profil",
|
|
314
|
-
event: "*",
|
|
315
|
-
filter: "owner_id=eq.${USER_ID}",
|
|
316
|
-
broadcast: "user_profil_updated",
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
schema: "public",
|
|
320
|
-
table: "user_addresses",
|
|
321
|
-
event: "*",
|
|
322
|
-
filter: "owner_id=eq.${USER_ID}",
|
|
323
|
-
broadcast: "user_address_updated",
|
|
324
|
-
},
|
|
325
306
|
],
|
|
326
|
-
},
|
|
307
|
+
},
|
|
308
|
+
authDashboard: [
|
|
309
|
+
{
|
|
310
|
+
key: "user",
|
|
311
|
+
title: "auth",
|
|
312
|
+
icon: "Dashboard",
|
|
313
|
+
componentExport: "DashboardPage",
|
|
314
|
+
entryPoint: "components/auth/dashboard",
|
|
315
|
+
order: 1,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
327
318
|
storage: {
|
|
328
319
|
buckets: [
|
|
329
320
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { AppLink, Button } from "@lastbrain/ui";
|
|
4
4
|
import { Avatar } from "@lastbrain/ui";
|
|
5
5
|
import {
|
|
6
6
|
Dropdown,
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from "@lastbrain/ui";
|
|
11
11
|
import * as LucideIcons from "lucide-react";
|
|
12
12
|
import type { User } from "@supabase/supabase-js";
|
|
13
|
+
import { useModuleTranslation, langHref } from "@lastbrain/app";
|
|
14
|
+
import { useLanguage } from "@lastbrain/app";
|
|
13
15
|
|
|
14
16
|
interface AccountButtonProps {
|
|
15
17
|
item: {
|
|
@@ -38,12 +40,15 @@ export const AccountButton = ({
|
|
|
38
40
|
accountMenu = [],
|
|
39
41
|
onLogout,
|
|
40
42
|
}: AccountButtonProps) => {
|
|
43
|
+
const { lang } = useLanguage();
|
|
44
|
+
const t = useModuleTranslation("auth");
|
|
45
|
+
|
|
41
46
|
if (!user)
|
|
42
47
|
return (
|
|
43
48
|
<>
|
|
44
49
|
<div className="block md:hidden">
|
|
45
50
|
<Button
|
|
46
|
-
as={
|
|
51
|
+
as={AppLink}
|
|
47
52
|
href="/signin"
|
|
48
53
|
radius="full"
|
|
49
54
|
isIconOnly
|
|
@@ -53,7 +58,7 @@ export const AccountButton = ({
|
|
|
53
58
|
<LucideIcons.LogIn size={16} />
|
|
54
59
|
</Button>
|
|
55
60
|
<Button
|
|
56
|
-
as={
|
|
61
|
+
as={AppLink}
|
|
57
62
|
href="/signup"
|
|
58
63
|
radius="full"
|
|
59
64
|
isIconOnly
|
|
@@ -66,23 +71,23 @@ export const AccountButton = ({
|
|
|
66
71
|
</div>
|
|
67
72
|
<div className="hidden md:block">
|
|
68
73
|
<Button
|
|
69
|
-
as={
|
|
74
|
+
as={AppLink}
|
|
70
75
|
href="/signin"
|
|
71
76
|
startContent={<LucideIcons.LogIn size={16} />}
|
|
72
77
|
variant="light"
|
|
73
78
|
color="primary"
|
|
74
79
|
>
|
|
75
|
-
|
|
80
|
+
{t("signin")}
|
|
76
81
|
</Button>
|
|
77
82
|
<Button
|
|
78
|
-
as={
|
|
83
|
+
as={AppLink}
|
|
79
84
|
href="/signup"
|
|
80
85
|
variant="flat"
|
|
81
86
|
className="ml-2"
|
|
82
87
|
color="secondary"
|
|
83
88
|
startContent={<LucideIcons.UserPlus2 size={16} />}
|
|
84
89
|
>
|
|
85
|
-
|
|
90
|
+
{t("signup")}
|
|
86
91
|
</Button>
|
|
87
92
|
</div>
|
|
88
93
|
</>
|
|
@@ -117,7 +122,9 @@ export const AccountButton = ({
|
|
|
117
122
|
items={[
|
|
118
123
|
{
|
|
119
124
|
key: "hello",
|
|
120
|
-
label:
|
|
125
|
+
label: `${t("hello")} ${
|
|
126
|
+
user?.user_metadata?.full_name || user.email
|
|
127
|
+
}`,
|
|
121
128
|
isReadOnly: true,
|
|
122
129
|
},
|
|
123
130
|
...accountMenu.map((item) => ({
|
|
@@ -130,7 +137,7 @@ export const AccountButton = ({
|
|
|
130
137
|
href:
|
|
131
138
|
item.path.includes("signout") || item.path.includes("logout")
|
|
132
139
|
? undefined
|
|
133
|
-
: item.path,
|
|
140
|
+
: langHref(item.path, lang),
|
|
134
141
|
})),
|
|
135
142
|
]}
|
|
136
143
|
>
|
|
@@ -151,7 +158,7 @@ export const AccountButton = ({
|
|
|
151
158
|
href={item.href}
|
|
152
159
|
onPress={item.isLogout ? () => onLogout?.() : undefined}
|
|
153
160
|
color={item.isLogout ? "danger" : "default"}
|
|
154
|
-
description={item.description}
|
|
161
|
+
description={!item.isLogout && item.description}
|
|
155
162
|
startContent={Icon && <Icon size={16} />}
|
|
156
163
|
isDisabled={item.isReadOnly}
|
|
157
164
|
isReadOnly={item.isReadOnly}
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
Avatar,
|
|
12
12
|
} from "@lastbrain/ui";
|
|
13
13
|
|
|
14
|
-
import { User, Mail, Calendar, Shield } from "lucide-react";
|
|
14
|
+
import { User, Mail, Calendar, Shield, LayoutDashboard } from "lucide-react";
|
|
15
|
+
import { useModuleTranslation } from "@lastbrain/core";
|
|
15
16
|
|
|
16
17
|
interface UserData {
|
|
17
18
|
id: string;
|
|
@@ -28,6 +29,7 @@ interface UserData {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export function DashboardPage() {
|
|
32
|
+
const t = useModuleTranslation("auth");
|
|
31
33
|
const [userData, setUserData] = useState<UserData | null>(null);
|
|
32
34
|
const [isLoading, setIsLoading] = useState(true);
|
|
33
35
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -59,7 +61,9 @@ export function DashboardPage() {
|
|
|
59
61
|
<div className="flex justify-center items-center min-h-[400px]">
|
|
60
62
|
<Spinner color="primary" size="lg">
|
|
61
63
|
{" "}
|
|
62
|
-
<span className="text-xs text-default-700">
|
|
64
|
+
<span className="text-xs text-default-700">
|
|
65
|
+
{t("dashboard.loading") || "Loading dashboard..."}
|
|
66
|
+
</span>
|
|
63
67
|
</Spinner>
|
|
64
68
|
</div>
|
|
65
69
|
);
|
|
@@ -70,7 +74,9 @@ export function DashboardPage() {
|
|
|
70
74
|
<div className="pt-12">
|
|
71
75
|
<Card className="max-w-2xl mx-auto">
|
|
72
76
|
<CardBody>
|
|
73
|
-
<p className="text-danger">
|
|
77
|
+
<p className="text-danger">
|
|
78
|
+
{t("dashboard.error") || "Error"}: {error}
|
|
79
|
+
</p>
|
|
74
80
|
</CardBody>
|
|
75
81
|
</Card>
|
|
76
82
|
</div>
|
|
@@ -87,10 +93,15 @@ export function DashboardPage() {
|
|
|
87
93
|
: "User";
|
|
88
94
|
|
|
89
95
|
return (
|
|
90
|
-
<div className="pt-
|
|
91
|
-
<
|
|
96
|
+
<div className="md:pt-8 max-w-6xl mx-auto">
|
|
97
|
+
<div className="flex flex-inline items-center gap-2 mb-4">
|
|
98
|
+
<LayoutDashboard size={24} />
|
|
99
|
+
<h1 className="text-3xl font-bold ">
|
|
100
|
+
{t("dashboard.title") || "Dashboard"}
|
|
101
|
+
</h1>
|
|
102
|
+
</div>
|
|
92
103
|
|
|
93
|
-
<div className="grid gap-6 md:grid-cols-2">
|
|
104
|
+
<div className="mx-0 px-0 grid gap-6 md:grid-cols-2">
|
|
94
105
|
{/* Profile Summary Card */}
|
|
95
106
|
<Card className="col-span-full md:col-span-1">
|
|
96
107
|
<CardHeader className="flex gap-3">
|
|
@@ -115,7 +126,7 @@ export function DashboardPage() {
|
|
|
115
126
|
<div className="flex items-center gap-2">
|
|
116
127
|
<Calendar className="w-4 h-4 text-default-400" />
|
|
117
128
|
<span className="text-small">
|
|
118
|
-
Member since{" "}
|
|
129
|
+
{t("dashboard.member_since") || "Member since"}{" "}
|
|
119
130
|
{new Date(userData.created_at).toLocaleDateString()}
|
|
120
131
|
</span>
|
|
121
132
|
</div>
|
|
@@ -132,25 +143,33 @@ export function DashboardPage() {
|
|
|
132
143
|
{/* Account Status Card */}
|
|
133
144
|
<Card>
|
|
134
145
|
<CardHeader>
|
|
135
|
-
<h3 className="text-lg font-semibold">
|
|
146
|
+
<h3 className="text-lg font-semibold">
|
|
147
|
+
{t("dashboard.account_status") || "Account Status"}
|
|
148
|
+
</h3>
|
|
136
149
|
</CardHeader>
|
|
137
150
|
<Divider />
|
|
138
151
|
<CardBody>
|
|
139
152
|
<div className="space-y-4">
|
|
140
153
|
<div className="flex justify-between items-center">
|
|
141
|
-
<span className="text-small">
|
|
154
|
+
<span className="text-small">
|
|
155
|
+
{t("dashboard.status") || "Status"}
|
|
156
|
+
</span>
|
|
142
157
|
<Chip color="success" size="sm" variant="flat">
|
|
143
|
-
Active
|
|
158
|
+
{t("dashboard.active") || "Active"}
|
|
144
159
|
</Chip>
|
|
145
160
|
</div>
|
|
146
161
|
<div className="flex justify-between items-center">
|
|
147
|
-
<span className="text-small">
|
|
162
|
+
<span className="text-small">
|
|
163
|
+
{t("dashboard.profile") || "Profile"}
|
|
164
|
+
</span>
|
|
148
165
|
<Chip
|
|
149
166
|
color={userData.profile ? "success" : "warning"}
|
|
150
167
|
size="sm"
|
|
151
168
|
variant="flat"
|
|
152
169
|
>
|
|
153
|
-
{userData.profile
|
|
170
|
+
{userData.profile
|
|
171
|
+
? t("dashboard.complete") || "Complete"
|
|
172
|
+
: t("dashboard.incomplete") || "Incomplete"}
|
|
154
173
|
</Chip>
|
|
155
174
|
</div>
|
|
156
175
|
</div>
|
|
@@ -172,7 +191,7 @@ export function DashboardPage() {
|
|
|
172
191
|
</Card>
|
|
173
192
|
)}
|
|
174
193
|
|
|
175
|
-
{/* Quick Stats
|
|
194
|
+
{/* Quick Stats
|
|
176
195
|
<Card className="col-span-full">
|
|
177
196
|
<CardHeader>
|
|
178
197
|
<h3 className="text-lg font-semibold">Quick Stats</h3>
|
|
@@ -203,7 +222,7 @@ export function DashboardPage() {
|
|
|
203
222
|
</div>
|
|
204
223
|
</div>
|
|
205
224
|
</CardBody>
|
|
206
|
-
</Card>
|
|
225
|
+
</Card> */}
|
|
207
226
|
</div>
|
|
208
227
|
</div>
|
|
209
228
|
);
|