@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.
Files changed (46) hide show
  1. package/dist/auth.build.config.d.ts.map +1 -1
  2. package/dist/auth.build.config.js +42 -51
  3. package/dist/components/AccountButton.d.ts.map +1 -1
  4. package/dist/components/AccountButton.js +9 -5
  5. package/dist/components/auth/dashboard.d.ts +2 -0
  6. package/dist/components/auth/dashboard.d.ts.map +1 -0
  7. package/dist/components/auth/dashboard.js +47 -0
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/web/admin/signup-stats.d.ts.map +1 -1
  12. package/dist/web/admin/signup-stats.js +4 -2
  13. package/dist/web/admin/user-detail.d.ts.map +1 -1
  14. package/dist/web/admin/user-detail.js +42 -17
  15. package/dist/web/admin/users-by-signup-source.d.ts.map +1 -1
  16. package/dist/web/admin/users-by-signup-source.js +18 -7
  17. package/dist/web/admin/users.d.ts.map +1 -1
  18. package/dist/web/admin/users.js +11 -6
  19. package/dist/web/auth/dashboard.d.ts.map +1 -1
  20. package/dist/web/auth/dashboard.js +7 -3
  21. package/dist/web/auth/folder.d.ts.map +1 -1
  22. package/dist/web/auth/folder.js +5 -3
  23. package/dist/web/auth/profile.d.ts.map +1 -1
  24. package/dist/web/auth/profile.js +13 -6
  25. package/dist/web/auth/reglage.d.ts.map +1 -1
  26. package/dist/web/auth/reglage.js +11 -6
  27. package/dist/web/public/SignInPage.d.ts.map +1 -1
  28. package/dist/web/public/SignInPage.js +14 -56
  29. package/dist/web/public/SignUpPage.d.ts.map +1 -1
  30. package/dist/web/public/SignUpPage.js +18 -11
  31. package/package.json +4 -3
  32. package/src/auth.build.config.ts +43 -52
  33. package/src/components/AccountButton.tsx +17 -10
  34. package/src/{web → components}/auth/dashboard.tsx +33 -14
  35. package/src/i18n/en.json +265 -0
  36. package/src/i18n/fr.json +262 -0
  37. package/src/index.ts +1 -1
  38. package/src/web/admin/signup-stats.tsx +10 -3
  39. package/src/web/admin/user-detail.tsx +135 -56
  40. package/src/web/admin/users-by-signup-source.tsx +60 -21
  41. package/src/web/admin/users.tsx +41 -18
  42. package/src/web/auth/folder.tsx +11 -3
  43. package/src/web/auth/profile.tsx +63 -29
  44. package/src/web/auth/reglage.tsx +43 -19
  45. package/src/web/public/SignInPage.tsx +32 -70
  46. 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 { useRouter, useSearchParams } from "next/navigation";
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 = useRouter();
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("Les mots de passe ne correspondent pas.");
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("Le mot de passe doit contenir au moins 6 caractères.");
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("/signin");
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-400", children: "Cr\u00E9ez 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: "Nom complet", type: "text", placeholder: "Jean Dupont", value: fullName, onChange: (e) => setFullName(e.target.value), startContent: _jsx(User, { className: "h-4 w-4 text-default-400" }), classNames: {
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 caract\u00E8res" }), _jsx(Input, { label: "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: {
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: "Cr\u00E9er 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: "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: ["D\u00E9j\u00E0 inscrit ?", " ", _jsx(Link, { href: redirectUrl
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-xs text-default-400", children: ["En cr\u00E9ant un compte, vous acceptez nos", " ", _jsx(Link, { href: "/legal/terms", className: "underline hover:text-secondary-500", children: "conditions d'utilisation" }), " ", "et notre", " ", _jsx(Link, { href: "/legal/privacy", className: "underline hover:text-secondary-500", children: "politique de confidentialit\u00E9" })] })] }) })] }));
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.16",
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/core": "^2.0.16",
36
- "@lastbrain/ui": "^2.0.16",
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",
@@ -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: "Notifications",
145
- description: "Vos notifications",
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: "Compte",
155
- description: "Gérer votre compte",
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: "Theme",
165
- description: "Changer le thème",
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: "Gestion des utilisateurs",
177
- description: "Gérez les utilisateurs de la plateforme",
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: "Statistiques d'inscriptions",
186
- description: "Suivez les inscriptions par source",
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: "Notifications",
194
- description: "Vos notifications",
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: "Compte",
204
- description: "Gérer votre compte",
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: "Theme",
214
- description: "Changer le thème",
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: "Tableau de bord",
226
- description: "Accédez à votre tableau de bord",
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: "Dossier",
235
- description: "Accédez à votre dossier personnel",
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: "Notifications",
244
- description: "Vos notifications",
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: "Compte",
254
- description: "Gérer votre compte",
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: "Theme",
264
- description: "Changer le thème",
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: "Mon profil",
276
- description: "Gérez vos informations personnelles",
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: "Paramètres",
285
- description: "Configurez votre compte",
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: "Déconnexion",
294
- description: "Se déconnecter",
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 { Button, Link } from "@lastbrain/ui";
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={Link}
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={Link}
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={Link}
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
- Se connecter
80
+ {t("signin")}
76
81
  </Button>
77
82
  <Button
78
- as={Link}
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
- S'inscrire
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: `Bonjour ${user?.user_metadata?.full_name || user.email}`,
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">Loading dashboard...</span>
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">Error: {error}</p>
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-12 pb-12 max-w-6xl mx-auto px-4">
91
- <h1 className="text-3xl font-bold mb-8">Dashboard</h1>
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">Account Status</h3>
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">Status</span>
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">Profile</span>
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 ? "Complete" : "Incomplete"}
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
  );