@lastbrain/app 0.1.29 → 0.1.31

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 (53) hide show
  1. package/dist/auth/useAuthSession.d.ts.map +1 -1
  2. package/dist/auth/useAuthSession.js +8 -2
  3. package/dist/components/NotificationContainer.d.ts +2 -0
  4. package/dist/components/NotificationContainer.d.ts.map +1 -0
  5. package/dist/components/NotificationContainer.js +8 -0
  6. package/dist/hooks/useNotifications.d.ts +29 -0
  7. package/dist/hooks/useNotifications.d.ts.map +1 -0
  8. package/dist/hooks/useNotifications.js +165 -0
  9. package/dist/hooks/useNotificationsSimple.d.ts +20 -0
  10. package/dist/hooks/useNotificationsSimple.d.ts.map +1 -0
  11. package/dist/hooks/useNotificationsSimple.js +37 -0
  12. package/dist/index.d.ts +4 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +4 -1
  15. package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
  16. package/dist/layouts/AdminLayoutWithSidebar.js +15 -3
  17. package/dist/layouts/AppProviders.d.ts +15 -2
  18. package/dist/layouts/AppProviders.d.ts.map +1 -1
  19. package/dist/layouts/AppProviders.js +21 -8
  20. package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
  21. package/dist/layouts/AuthLayoutWithSidebar.js +13 -3
  22. package/dist/layouts/PublicLayout.js +1 -1
  23. package/dist/layouts/PublicLayoutWithSidebar.d.ts +8 -0
  24. package/dist/layouts/PublicLayoutWithSidebar.d.ts.map +1 -0
  25. package/dist/layouts/PublicLayoutWithSidebar.js +19 -0
  26. package/dist/layouts/RootLayout.d.ts +3 -1
  27. package/dist/layouts/RootLayout.d.ts.map +1 -1
  28. package/dist/layouts/RootLayout.js +3 -2
  29. package/dist/scripts/init-app.d.ts.map +1 -1
  30. package/dist/scripts/init-app.js +159 -5
  31. package/dist/scripts/module-build.d.ts.map +1 -1
  32. package/dist/scripts/module-build.js +52 -0
  33. package/dist/styles.css +1 -1
  34. package/dist/templates/DefaultDoc.d.ts.map +1 -1
  35. package/dist/templates/DefaultDoc.js +64 -1
  36. package/dist/templates/DocPage.d.ts.map +1 -1
  37. package/dist/templates/DocPage.js +7 -0
  38. package/package.json +1 -2
  39. package/src/auth/useAuthSession.ts +6 -2
  40. package/src/components/NotificationContainer.tsx +20 -0
  41. package/src/hooks/useNotifications.ts +216 -0
  42. package/src/index.ts +4 -1
  43. package/src/layouts/AdminLayoutWithSidebar.tsx +28 -4
  44. package/src/layouts/AppProviders.tsx +50 -13
  45. package/src/layouts/AuthLayoutWithSidebar.tsx +25 -4
  46. package/src/layouts/PublicLayout.tsx +1 -1
  47. package/src/layouts/PublicLayoutWithSidebar.tsx +56 -0
  48. package/src/layouts/RootLayout.tsx +10 -2
  49. package/src/scripts/generate-realtime-config.mjs +183 -0
  50. package/src/scripts/init-app.ts +172 -5
  51. package/src/scripts/module-build.ts +63 -0
  52. package/src/templates/DefaultDoc.tsx +265 -0
  53. package/src/templates/DocPage.tsx +7 -0
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthSession.d.ts","sourceRoot":"","sources":["../../src/auth/useAuthSession.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,wBAAgB,cAAc;;;;EA+C7B"}
1
+ {"version":3,"file":"useAuthSession.d.ts","sourceRoot":"","sources":["../../src/auth/useAuthSession.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,wBAAgB,cAAc;;;;EAmD7B"}
@@ -17,6 +17,10 @@ export function useAuthSession() {
17
17
  console.error("Error checking superadmin status:", error);
18
18
  setIsSuperAdmin(false);
19
19
  }
20
+ finally {
21
+ // Ne terminer le loading qu'après avoir vérifié le status admin
22
+ setLoading(false);
23
+ }
20
24
  };
21
25
  // Récupérer la session initiale
22
26
  supabaseBrowserClient.auth.getSession().then(({ data: { session } }) => {
@@ -24,7 +28,9 @@ export function useAuthSession() {
24
28
  if (session?.user) {
25
29
  checkSuperAdmin(session.user.id);
26
30
  }
27
- setLoading(false);
31
+ else {
32
+ setLoading(false);
33
+ }
28
34
  });
29
35
  // Écouter les changements d'auth
30
36
  const { data: { subscription }, } = supabaseBrowserClient.auth.onAuthStateChange((_event, session) => {
@@ -34,8 +40,8 @@ export function useAuthSession() {
34
40
  }
35
41
  else {
36
42
  setIsSuperAdmin(false);
43
+ setLoading(false);
37
44
  }
38
- setLoading(false);
39
45
  });
40
46
  return () => subscription.unsubscribe();
41
47
  }, []);
@@ -0,0 +1,2 @@
1
+ export declare function NotificationContainer(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=NotificationContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationContainer.d.ts","sourceRoot":"","sources":["../../src/components/NotificationContainer.tsx"],"names":[],"mappings":"AAKA,wBAAgB,qBAAqB,4CAcpC"}
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Notification } from "@lastbrain/ui";
4
+ import { useNotifications } from "../layouts/AppProviders.js";
5
+ export function NotificationContainer() {
6
+ const { data, loading, markAsRead, markAllAsRead, deleteNotification } = useNotifications();
7
+ return (_jsx(Notification, { notifications: data.notifications, unreadCount: data.unreadCount, loading: loading, onMarkAsRead: markAsRead, onMarkAllAsRead: markAllAsRead, onDelete: deleteNotification }));
8
+ }
@@ -0,0 +1,29 @@
1
+ import type { User } from "@supabase/supabase-js";
2
+ export interface UserNotification {
3
+ id: string;
4
+ owner_id: string;
5
+ title: string;
6
+ body?: string;
7
+ type: string;
8
+ read: boolean;
9
+ created_at: string;
10
+ updated_at: string;
11
+ }
12
+ export interface NotificationsData {
13
+ notifications: UserNotification[];
14
+ unreadCount: number;
15
+ }
16
+ export declare function useNotifications(user?: User | null): {
17
+ data: NotificationsData;
18
+ loading: boolean;
19
+ error: string | null;
20
+ refetch: () => Promise<void>;
21
+ markAsRead: (notificationId: string) => Promise<void>;
22
+ markAllAsRead: () => Promise<void>;
23
+ deleteNotification: (notificationId: string) => Promise<void>;
24
+ isEmpty: boolean;
25
+ hasUnread: boolean;
26
+ realtimeActive: boolean;
27
+ lastRealtimePayload: any;
28
+ };
29
+ //# sourceMappingURL=useNotifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNotifications.d.ts","sourceRoot":"","sources":["../../src/hooks/useNotifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI;;;;;iCAwExB,MAAM;;yCAiEN,MAAM;;;;;EAwDhC"}
@@ -0,0 +1,165 @@
1
+ "use client";
2
+ import { useState, useEffect, useCallback } from "react";
3
+ import { useTableRealtime, supabaseBrowserClient } from "@lastbrain/core";
4
+ export function useNotifications(user) {
5
+ const [data, setData] = useState({
6
+ notifications: [],
7
+ unreadCount: 0,
8
+ });
9
+ const [loading, setLoading] = useState(true);
10
+ const [error, setError] = useState(null);
11
+ const fetchNotifications = useCallback(async () => {
12
+ if (!user?.id) {
13
+ if (user === null) {
14
+ // Utilisateur explicitement non connecté
15
+ setData({ notifications: [], unreadCount: 0 });
16
+ setLoading(false);
17
+ }
18
+ // Si user === undefined, on est encore en train de charger l'auth, on ne fait rien
19
+ return;
20
+ }
21
+ try {
22
+ setLoading(true);
23
+ setError(null);
24
+ // Utilisation directe du client Supabase côté navigateur
25
+ const { data: notifications, error: fetchError } = await supabaseBrowserClient
26
+ .from("user_notifications")
27
+ .select("*")
28
+ .eq("owner_id", user.id)
29
+ .order("created_at", { ascending: false });
30
+ if (fetchError) {
31
+ throw fetchError;
32
+ }
33
+ const unreadCount = notifications?.filter((n) => !n.read).length || 0;
34
+ setData({
35
+ notifications: notifications || [],
36
+ unreadCount,
37
+ });
38
+ }
39
+ catch (err) {
40
+ setError(err instanceof Error
41
+ ? err.message
42
+ : "Erreur lors du chargement des notifications");
43
+ console.error("[useNotifications] Erreur:", err);
44
+ }
45
+ finally {
46
+ setLoading(false);
47
+ }
48
+ }, [user]);
49
+ // Utiliser le hook realtime scalable pour les notifications
50
+ const { tick: realtimeTick, lastPayload } = useTableRealtime("user_notifications", {
51
+ eventName: "user_notifications_updated",
52
+ onUpdate: (payload) => {
53
+ console.log("🔔 Nouvelle notification détectée via realtime:", payload);
54
+ console.log("🔔 User ID actuel:", user?.id);
55
+ // Recharger immédiatement les notifications
56
+ if (user?.id) {
57
+ console.log("🔔 Rechargement des notifications...");
58
+ fetchNotifications();
59
+ }
60
+ },
61
+ });
62
+ // Marquer une notification comme lue
63
+ const markAsRead = useCallback(async (notificationId) => {
64
+ if (!user?.id)
65
+ return;
66
+ try {
67
+ const { error: updateError } = await supabaseBrowserClient
68
+ .from("user_notifications")
69
+ .update({
70
+ read: true,
71
+ updated_at: new Date().toISOString(),
72
+ })
73
+ .eq("id", notificationId)
74
+ .eq("owner_id", user.id);
75
+ if (updateError) {
76
+ throw updateError;
77
+ }
78
+ // Mettre à jour localement en attendant le realtime
79
+ setData((prev) => ({
80
+ ...prev,
81
+ notifications: prev.notifications.map((n) => n.id === notificationId ? { ...n, read: true } : n),
82
+ unreadCount: Math.max(0, prev.unreadCount - 1),
83
+ }));
84
+ }
85
+ catch (err) {
86
+ console.error("Erreur mark as read:", err);
87
+ throw err;
88
+ }
89
+ }, [user?.id]);
90
+ // Marquer toutes les notifications comme lues
91
+ const markAllAsRead = useCallback(async () => {
92
+ if (!user?.id || data.unreadCount === 0)
93
+ return;
94
+ try {
95
+ const { error: updateError } = await supabaseBrowserClient
96
+ .from("user_notifications")
97
+ .update({
98
+ read: true,
99
+ updated_at: new Date().toISOString(),
100
+ })
101
+ .eq("owner_id", user.id)
102
+ .eq("read", false);
103
+ if (updateError) {
104
+ throw updateError;
105
+ }
106
+ // Mettre à jour localement
107
+ setData((prev) => ({
108
+ ...prev,
109
+ notifications: prev.notifications.map((n) => ({ ...n, read: true })),
110
+ unreadCount: 0,
111
+ }));
112
+ }
113
+ catch (err) {
114
+ console.error("Erreur mark all as read:", err);
115
+ throw err;
116
+ }
117
+ }, [user?.id, data.unreadCount]);
118
+ // Supprimer une notification
119
+ const deleteNotification = useCallback(async (notificationId) => {
120
+ if (!user?.id)
121
+ return;
122
+ try {
123
+ const { error: deleteError } = await supabaseBrowserClient
124
+ .from("user_notifications")
125
+ .delete()
126
+ .eq("id", notificationId)
127
+ .eq("owner_id", user.id);
128
+ if (deleteError) {
129
+ throw deleteError;
130
+ }
131
+ // Mettre à jour localement
132
+ setData((prev) => {
133
+ const notification = prev.notifications.find((n) => n.id === notificationId);
134
+ return {
135
+ notifications: prev.notifications.filter((n) => n.id !== notificationId),
136
+ unreadCount: notification && !notification.read
137
+ ? Math.max(0, prev.unreadCount - 1)
138
+ : prev.unreadCount,
139
+ };
140
+ });
141
+ }
142
+ catch (err) {
143
+ console.error("Erreur delete notification:", err);
144
+ throw err;
145
+ }
146
+ }, [user?.id]);
147
+ // Charger les notifications initiales
148
+ useEffect(() => {
149
+ fetchNotifications();
150
+ }, [fetchNotifications]);
151
+ return {
152
+ data,
153
+ loading,
154
+ error,
155
+ refetch: fetchNotifications,
156
+ markAsRead,
157
+ markAllAsRead,
158
+ deleteNotification,
159
+ isEmpty: data.notifications.length === 0,
160
+ hasUnread: data.unreadCount > 0,
161
+ // Informations realtime
162
+ realtimeActive: realtimeTick > 0,
163
+ lastRealtimePayload: lastPayload,
164
+ };
165
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Hook simple pour utiliser les notifications partout dans l'app
3
+ * Wrapper autour du contexte pour plus de simplicité
4
+ */
5
+ export declare function useNotificationsSimple(): {
6
+ notifications: import("./useNotifications.js").UserNotification[];
7
+ unreadCount: number;
8
+ loading: boolean;
9
+ error: string | null;
10
+ isEmpty: boolean;
11
+ hasUnread: boolean;
12
+ refetch: () => Promise<void>;
13
+ markAsRead: (id: string) => Promise<void>;
14
+ markAllAsRead: () => Promise<void>;
15
+ deleteNotification: (id: string) => Promise<void>;
16
+ realtimeActive: boolean;
17
+ lastUpdate: any;
18
+ };
19
+ export default useNotificationsSimple;
20
+ //# sourceMappingURL=useNotificationsSimple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNotificationsSimple.d.ts","sourceRoot":"","sources":["../../src/hooks/useNotificationsSimple.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,sBAAsB;;;;;;;;;;;;;EAmCrC;AAED,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { useNotifications as useNotificationsContext } from "../layouts/AppProviders.js";
2
+ /**
3
+ * Hook simple pour utiliser les notifications partout dans l'app
4
+ * Wrapper autour du contexte pour plus de simplicité
5
+ */
6
+ export function useNotificationsSimple() {
7
+ const context = useNotificationsContext();
8
+ // Log uniquement en cas de problème pour le debug
9
+ if (context.error || (context.data.notifications.length > 0 && process.env.NODE_ENV === 'development')) {
10
+ console.log("[useNotificationsSimple] État:", {
11
+ dataNotifications: context.data.notifications?.length || 0,
12
+ dataUnreadCount: context.data.unreadCount,
13
+ loading: context.loading,
14
+ error: context.error,
15
+ realtimeActive: context.realtimeActive
16
+ });
17
+ }
18
+ return {
19
+ // Données principales
20
+ notifications: context.data.notifications,
21
+ unreadCount: context.data.unreadCount,
22
+ // États
23
+ loading: context.loading,
24
+ error: context.error,
25
+ isEmpty: context.isEmpty,
26
+ hasUnread: context.hasUnread,
27
+ // Actions
28
+ refetch: context.refetch,
29
+ markAsRead: context.markAsRead,
30
+ markAllAsRead: context.markAllAsRead,
31
+ deleteNotification: context.deleteNotification,
32
+ // Realtime info
33
+ realtimeActive: context.realtimeActive,
34
+ lastUpdate: context.lastRealtimePayload,
35
+ };
36
+ }
37
+ export default useNotificationsSimple;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- export { AppProviders, useAuth, useModules, useNotifications, } from "./layouts/AppProviders.js";
1
+ export { AppProviders, useAuth, useModules, useNotifications as useNotificationsContext, } from "./layouts/AppProviders.js";
2
+ export { useNotifications } from "./hooks/useNotifications.js";
3
+ export { NotificationContainer } from "./components/NotificationContainer.js";
2
4
  export { useAuthSession } from "./auth/useAuthSession.js";
3
5
  export { signOut, signIn } from "./auth/authHelpers.js";
4
6
  export { RootLayout } from "./layouts/RootLayout.js";
5
7
  export { PublicLayout } from "./layouts/PublicLayout.js";
8
+ export { PublicLayoutWithSidebar } from "./layouts/PublicLayoutWithSidebar.js";
6
9
  export { AuthLayout } from "./layouts/AuthLayout.js";
7
10
  export { AuthLayoutWithSidebar } from "./layouts/AuthLayoutWithSidebar.js";
8
11
  export { AdminLayout } from "./layouts/AdminLayout.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,EACV,gBAAgB,IAAI,uBAAuB,GAC5C,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
- export { AppProviders, useAuth, useModules, useNotifications, } from "./layouts/AppProviders.js";
1
+ export { AppProviders, useAuth, useModules, useNotifications as useNotificationsContext, } from "./layouts/AppProviders.js";
2
+ export { useNotifications } from "./hooks/useNotifications.js";
3
+ export { NotificationContainer } from "./components/NotificationContainer.js";
2
4
  export { useAuthSession } from "./auth/useAuthSession.js";
3
5
  export { signOut, signIn } from "./auth/authHelpers.js";
4
6
  export { RootLayout } from "./layouts/RootLayout.js";
5
7
  export { PublicLayout } from "./layouts/PublicLayout.js";
8
+ export { PublicLayoutWithSidebar } from "./layouts/PublicLayoutWithSidebar.js";
6
9
  export { AuthLayout } from "./layouts/AuthLayout.js";
7
10
  export { AuthLayoutWithSidebar } from "./layouts/AuthLayoutWithSidebar.js";
8
11
  export { AdminLayout } from "./layouts/AdminLayout.js";
@@ -1 +1 @@
1
- {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAMA,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,2BAA2B,2CAkB7B"}
1
+ {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAOA,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,2BAA2B,2CAyC7B"}
@@ -1,9 +1,21 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AdminLayout } from "./AdminLayout.js";
4
- import { AppAside } from "@lastbrain/ui";
4
+ import { AppAside, AppAsideSkeleton } from "@lastbrain/ui";
5
5
  import { useAuthSession } from "../auth/useAuthSession.js";
6
+ import { usePathname } from "next/navigation";
6
7
  export function AdminLayoutWithSidebar({ children, menuConfig, className = "", }) {
7
- const { isSuperAdmin } = useAuthSession();
8
- return (_jsxs("div", { className: "flex min-h-screen", children: [menuConfig && (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, className: className })), _jsx("div", { className: `flex-1 ${menuConfig ? "lg:ml-72" : ""}`, children: _jsx(AdminLayout, { children: children }) })] }));
8
+ const { isSuperAdmin, loading, user } = useAuthSession();
9
+ const pathname = usePathname();
10
+ // Détecter si on est dans la section admin pour le skeleton
11
+ const isAdminSection = pathname.startsWith("/admin");
12
+ // Vérifier si menuConfig est vraiment disponible et valide
13
+ const hasValidMenuConfig = menuConfig &&
14
+ typeof menuConfig === "object" &&
15
+ (menuConfig.admin?.length > 0 ||
16
+ menuConfig.auth?.length > 0 ||
17
+ menuConfig.public?.length > 0);
18
+ // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
19
+ const shouldShowSkeleton = loading || !hasValidMenuConfig;
20
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: "flex-1 lg:ml-72", children: _jsx(AdminLayout, { children: children }) })] }));
9
21
  }
@@ -1,14 +1,27 @@
1
1
  import type { User } from "@supabase/supabase-js";
2
+ import type { ModuleRealtimeConfig } from "@lastbrain/core";
3
+ import type { NotificationsData } from "../hooks/useNotifications.js";
2
4
  export declare function useModules(): import("@lastbrain/core").ModuleBuildConfig[];
3
5
  export declare function useNotifications(): {
4
- messages: string[];
6
+ data: NotificationsData;
7
+ loading: boolean;
8
+ error: string | null;
9
+ refetch: () => Promise<void>;
10
+ markAsRead: (id: string) => Promise<void>;
11
+ markAllAsRead: () => Promise<void>;
12
+ deleteNotification: (id: string) => Promise<void>;
13
+ isEmpty: boolean;
14
+ hasUnread: boolean;
15
+ realtimeActive: boolean;
16
+ lastRealtimePayload: unknown;
5
17
  };
6
18
  export declare function useAuth(): {
7
19
  user: User | null;
8
20
  loading: boolean;
9
21
  isSuperAdmin: boolean;
10
22
  };
11
- export declare function AppProviders({ children }: {
23
+ export declare function AppProviders({ children, realtimeConfig, }: {
12
24
  children: React.ReactNode;
25
+ realtimeConfig?: ModuleRealtimeConfig[];
13
26
  }): import("react/jsx-runtime").JSX.Element;
14
27
  //# sourceMappingURL=AppProviders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAclD,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;cAf4B,MAAM,EAAE;EAiBnE;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CA0BvE"}
1
+ {"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layouts/AppProviders.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAuCtE,wBAAgB,UAAU,kDAEzB;AAED,wBAAgB,gBAAgB;UAvCxB,iBAAiB;aACd,OAAO;WACT,MAAM,GAAG,IAAI;aACX,MAAM,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;mBAC1B,MAAM,OAAO,CAAC,IAAI,CAAC;wBACd,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;aACxC,OAAO;eACL,OAAO;oBACF,OAAO;yBACF,OAAO;EA+B7B;AAED,wBAAgB,OAAO;UAjBf,IAAI,GAAG,IAAI;aACR,OAAO;kBACF,OAAO;EAiBtB;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,cAAmB,GACpB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACzC,2CA4BA"}
@@ -3,9 +3,23 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { createContext, useContext, useMemo } from "react";
4
4
  import { getModuleConfigs } from "../modules/module-loader.js";
5
5
  import { ToastProvider } from "@lastbrain/ui";
6
+ import { RealtimeProvider } from "@lastbrain/core";
6
7
  import { useAuthSession } from "../auth/useAuthSession.js";
8
+ import { useNotifications as useNotificationsHook } from "../hooks/useNotifications.js";
7
9
  const ModuleContext = createContext(getModuleConfigs());
8
- const NotificationContext = createContext({ messages: [] });
10
+ const NotificationContext = createContext({
11
+ data: { notifications: [], unreadCount: 0 },
12
+ loading: true,
13
+ error: null,
14
+ refetch: async () => { },
15
+ markAsRead: async () => { },
16
+ markAllAsRead: async () => { },
17
+ deleteNotification: async () => { },
18
+ isEmpty: true,
19
+ hasUnread: false,
20
+ realtimeActive: false,
21
+ lastRealtimePayload: null,
22
+ });
9
23
  const AuthContext = createContext({
10
24
  user: null,
11
25
  loading: true,
@@ -20,16 +34,15 @@ export function useNotifications() {
20
34
  export function useAuth() {
21
35
  return useContext(AuthContext);
22
36
  }
23
- export function AppProviders({ children }) {
37
+ export function AppProviders({ children, realtimeConfig = [], }) {
24
38
  const modules = useMemo(() => getModuleConfigs(), []);
25
- const notifications = useMemo(() => ({ messages: [] }), []);
26
- const { user, loading, isSuperAdmin } = useAuthSession();
27
- // const router = useRouter();
28
- const authValue = useMemo(() => ({ user, loading, isSuperAdmin }), [user, loading, isSuperAdmin]);
29
- // const handleLogout = async () => {
39
+ const { user, loading: authLoading, isSuperAdmin } = useAuthSession();
40
+ // Hook de notifications seulement quand l'auth est prête
41
+ const notificationsData = useNotificationsHook(user);
42
+ const authValue = useMemo(() => ({ user, loading: authLoading, isSuperAdmin }), [user, authLoading, isSuperAdmin]); // const handleLogout = async () => {
30
43
  // const { signOut } = await import("../auth/authHelpers.js");
31
44
  // await signOut();
32
45
  // router.push("/auth/signin");
33
46
  // };
34
- return (_jsx(AuthContext.Provider, { value: authValue, children: _jsx(ModuleContext.Provider, { value: modules, children: _jsxs(NotificationContext.Provider, { value: notifications, children: [children, _jsx(ToastProvider, { placement: "top-right", toastOffset: 75 })] }) }) }));
47
+ return (_jsx(AuthContext.Provider, { value: authValue, children: _jsx(ModuleContext.Provider, { value: modules, children: _jsx(NotificationContext.Provider, { value: notificationsData, children: _jsxs(RealtimeProvider, { userId: user?.id, config: realtimeConfig, children: [children, _jsx(ToastProvider, { placement: "bottom-right", toastOffset: 5 })] }) }) }) }));
35
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAMA,UAAU,0BAA0B;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,0BAA0B,2CAkB5B"}
1
+ {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAMA,UAAU,0BAA0B;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,0BAA0B,2CAuC5B"}
@@ -1,9 +1,19 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AuthLayout } from "./AuthLayout.js";
4
- import { AppAside } from "@lastbrain/ui";
4
+ import { AppAside, AppAsideSkeleton } from "@lastbrain/ui";
5
5
  import { useAuthSession } from "../auth/useAuthSession.js";
6
6
  export function AuthLayoutWithSidebar({ children, menuConfig, className = "", }) {
7
- const { isSuperAdmin } = useAuthSession();
8
- return (_jsxs("div", { className: "flex min-h-screen", children: [menuConfig && (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, className: className })), _jsx("div", { className: `flex-1 ${menuConfig ? "lg:ml-72" : ""}`, children: _jsx(AuthLayout, { children: children }) })] }));
7
+ const { isSuperAdmin, loading, user } = useAuthSession();
8
+ // Pour la section auth, isAdminSection sera false
9
+ const isAdminSection = false;
10
+ // Vérifier si menuConfig est vraiment disponible et valide
11
+ const hasValidMenuConfig = menuConfig &&
12
+ typeof menuConfig === "object" &&
13
+ (menuConfig.admin?.length > 0 ||
14
+ menuConfig.auth?.length > 0 ||
15
+ menuConfig.public?.length > 0);
16
+ // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
17
+ const shouldShowSkeleton = loading || !hasValidMenuConfig;
18
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: "flex-1 lg:ml-72", children: _jsx(AuthLayout, { children: children }) })] }));
9
19
  }
@@ -1,5 +1,5 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  export function PublicLayout({ children }) {
4
- return _jsx("section", { className: " px-4 ", children: children });
4
+ return _jsx("section", { className: " ", children: children });
5
5
  }
@@ -0,0 +1,8 @@
1
+ interface PublicLayoutWithSidebarProps {
2
+ children: React.ReactNode;
3
+ menuConfig?: any;
4
+ className?: string;
5
+ }
6
+ export declare function PublicLayoutWithSidebar({ children, menuConfig, className, }: PublicLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=PublicLayoutWithSidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublicLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayoutWithSidebar.tsx"],"names":[],"mappings":"AAMA,UAAU,4BAA4B;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,4BAA4B,2CAuC9B"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { PublicLayout } from "./PublicLayout.js";
4
+ import { AppAside, AppAsideSkeleton } from "@lastbrain/ui";
5
+ import { useAuthSession } from "../auth/useAuthSession.js";
6
+ export function PublicLayoutWithSidebar({ children, menuConfig, className = "", }) {
7
+ const { user, loading } = useAuthSession();
8
+ // Pour la section public, isAdminSection sera false
9
+ const isAdminSection = false;
10
+ // Vérifier si menuConfig est vraiment disponible et valide
11
+ const hasValidMenuConfig = menuConfig &&
12
+ typeof menuConfig === "object" &&
13
+ (menuConfig.admin?.length > 0 ||
14
+ menuConfig.auth?.length > 0 ||
15
+ menuConfig.public?.length > 0);
16
+ // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
17
+ const shouldShowSkeleton = loading || !hasValidMenuConfig;
18
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: false, isAuthenticated: !!user, className: className })), _jsx("div", { className: "flex-1 lg:ml-72", children: _jsx(PublicLayout, { children: children }) })] }));
19
+ }
@@ -1,4 +1,6 @@
1
- export declare function RootLayout({ children }: {
1
+ import type { ModuleRealtimeConfig } from "@lastbrain/core";
2
+ export declare function RootLayout({ children, realtimeConfig, }: {
2
3
  children: React.ReactNode;
4
+ realtimeConfig?: ModuleRealtimeConfig[];
3
5
  }): import("react/jsx-runtime").JSX.Element;
4
6
  //# sourceMappingURL=RootLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/RootLayout.tsx"],"names":[],"mappings":"AAMA,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAmBrE"}
1
+ {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/RootLayout.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,cAAmB,GACpB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACzC,2CAmBA"}
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { ThemeProvider } from "next-themes";
4
4
  import { AppProviders } from "./AppProviders.js";
5
5
  // Note: L'app Next.js doit importer son propre globals.css dans son layout
6
- export function RootLayout({ children }) {
7
- return (_jsx("html", { lang: "fr", suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { children: _jsx("div", { className: " min-h-screen bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-white", children: children }) }) }) }) }));
6
+ // Note: La configuration realtime doit être fournie par l'app qui utilise ce layout
7
+ export function RootLayout({ children, realtimeConfig = [], }) {
8
+ return (_jsx("html", { lang: "fr", suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { realtimeConfig: realtimeConfig, children: _jsx("div", { className: " min-h-screen bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-white", children: children }) }) }) }) }));
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBAwMpD"}
1
+ {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBAyMpD"}