Skip to content

Commit f7ea62f

Browse files
committed
Adding Sessions and doc images
1 parent 4fe5f97 commit f7ea62f

File tree

12 files changed

+783
-74
lines changed

12 files changed

+783
-74
lines changed
63.4 KB
Loading
63.8 KB
Loading
79.6 KB
Loading
54.9 KB
Loading
17.8 KB
Loading
11.2 KB
Loading

docs/modules/ROOT/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
** xref:Templates/Ecommerce.adoc[Ecommerce]
88
* Components
99
** xref:Components/Chatbot.adoc[Chatbot]
10+
** xref:Components/Card.adoc[Card]
1011
** xref:Components/ConnectionModal.adoc[ConnectionModal]
1112
** xref:Components/Header.adoc[Header]
1213
** xref:Components/PageNotFound.adoc[PageNotFound]

src/App.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import Movie from './templates/movie/Home';
1414
import ECommerce from './templates/ecommerce/Home';
1515

1616
import DemoCards from './templates/shared/components/DemoCards';
17-
import Chatbot from './templates/shared/components/Chatbot';
18-
import messagesData from './templates/shared/assets/ChatbotMessages.json';
17+
import ChatbotDemo from './templates/shared/components/ChatbotDemo';
1918
import ConnectionModal from './templates/shared/components/ConnectionModal';
2019
import Header from './templates/shared/components/Header';
2120
import User from './templates/shared/components/User';
@@ -25,7 +24,6 @@ import { FileContextProvider } from './context/connectionFile';
2524
import './ConnectionModal.css';
2625

2726
function App() {
28-
const messages = messagesData.listMessages;
2927
const [activeTab, setActiveTab] = useState<string>('Home');
3028
return (
3129
<BrowserRouter>
@@ -44,7 +42,7 @@ function App() {
4442
</FileContextProvider>
4543
}
4644
/>
47-
<Route path='/chat-widget-preview' element={<Chatbot messages={messages} />} />
45+
<Route path='/chat-widget-preview' element={<ChatbotDemo />} />
4846
<Route
4947
path='/header-preview'
5048
element={

src/context/ChatSessionContext.tsx

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
import React, { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
2+
3+
export interface ChatMessage {
4+
id: number;
5+
user: string;
6+
message: string;
7+
datetime: string;
8+
isTyping?: boolean;
9+
src?: Array<string>;
10+
}
11+
12+
export interface ChatSession {
13+
id: string;
14+
title: string;
15+
messages: ChatMessage[];
16+
createdAt: string;
17+
updatedAt: string;
18+
}
19+
20+
interface ChatSessionContextType {
21+
sessions: ChatSession[];
22+
currentSessionId: string | null;
23+
currentSession: ChatSession | null;
24+
createNewSession: (title?: string) => string;
25+
switchSession: (sessionId: string) => void;
26+
deleteSession: (sessionId: string) => void;
27+
addMessageToCurrentSession: (message: ChatMessage) => void;
28+
updateMessageInCurrentSession: (messageId: number, updatedMessage: ChatMessage) => void;
29+
updateSessionTitle: (sessionId: string, title: string) => void;
30+
clearAllSessions: () => void;
31+
}
32+
33+
const ChatSessionContext = createContext<ChatSessionContextType | undefined>(undefined);
34+
35+
export const useChatSession = () => {
36+
const context = useContext(ChatSessionContext);
37+
if (!context) {
38+
throw new Error('useChatSession must be used within a ChatSessionProvider');
39+
}
40+
return context;
41+
};
42+
43+
interface ChatSessionProviderProps {
44+
children: ReactNode;
45+
initialSessions?: ChatSession[];
46+
}
47+
48+
const STORAGE_KEY = 'neo4j-chat-sessions';
49+
const CURRENT_SESSION_KEY = 'neo4j-current-session';
50+
51+
const loadSessionsFromStorage = (): ChatSession[] => {
52+
try {
53+
const stored = localStorage.getItem(STORAGE_KEY);
54+
if (stored) {
55+
return JSON.parse(stored);
56+
}
57+
} catch (error) {
58+
// Silently handle localStorage errors
59+
}
60+
return [];
61+
};
62+
63+
const loadCurrentSessionIdFromStorage = (): string | null => {
64+
try {
65+
return localStorage.getItem(CURRENT_SESSION_KEY);
66+
} catch (error) {
67+
// Silently handle localStorage errors
68+
}
69+
return null;
70+
};
71+
72+
const saveSessionsToStorage = (sessions: ChatSession[]): void => {
73+
try {
74+
localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
75+
} catch (error) {
76+
// Silently handle localStorage errors
77+
}
78+
};
79+
80+
const saveCurrentSessionIdToStorage = (sessionId: string | null): void => {
81+
try {
82+
if (sessionId) {
83+
localStorage.setItem(CURRENT_SESSION_KEY, sessionId);
84+
} else {
85+
localStorage.removeItem(CURRENT_SESSION_KEY);
86+
}
87+
} catch (error) {
88+
// Silently handle localStorage errors
89+
}
90+
};
91+
92+
export const ChatSessionProvider: React.FC<ChatSessionProviderProps> = ({
93+
children,
94+
initialSessions = []
95+
}) => {
96+
const [sessions, setSessions] = useState<ChatSession[]>(() => {
97+
const storedSessions = loadSessionsFromStorage();
98+
if (storedSessions.length > 0) {
99+
return storedSessions;
100+
}
101+
return initialSessions;
102+
});
103+
104+
const [currentSessionId, setCurrentSessionId] = useState<string | null>(() => {
105+
const storedSessions = loadSessionsFromStorage();
106+
if (storedSessions.length > 0) {
107+
const storedCurrentId = loadCurrentSessionIdFromStorage();
108+
if (storedCurrentId && storedSessions.find(s => s.id === storedCurrentId)) {
109+
return storedCurrentId;
110+
}
111+
return storedSessions[0].id;
112+
}
113+
return initialSessions.length > 0 ? initialSessions[0].id : null;
114+
});
115+
116+
const currentSession = sessions.find(session => session.id === currentSessionId) || null;
117+
118+
useEffect(() => {
119+
saveSessionsToStorage(sessions);
120+
}, [sessions]);
121+
122+
useEffect(() => {
123+
saveCurrentSessionIdToStorage(currentSessionId);
124+
}, [currentSessionId]);
125+
126+
const createNewSession = useCallback((title?: string): string => {
127+
const now = new Date();
128+
const newSessionId = `session-${Date.now()}`;
129+
const newSession: ChatSession = {
130+
id: newSessionId,
131+
title: title || `Chat ${sessions.length + 1}`,
132+
messages: [],
133+
createdAt: now.toISOString(),
134+
updatedAt: now.toISOString(),
135+
};
136+
137+
setSessions(prev => [newSession, ...prev]);
138+
setCurrentSessionId(newSessionId);
139+
return newSessionId;
140+
}, [sessions.length]);
141+
142+
const switchSession = useCallback((sessionId: string) => {
143+
setCurrentSessionId(sessionId);
144+
}, []);
145+
146+
const deleteSession = useCallback((sessionId: string) => {
147+
setSessions(prev => {
148+
const filtered = prev.filter(session => session.id !== sessionId);
149+
150+
if (sessionId === currentSessionId) {
151+
if (filtered.length > 0) {
152+
setCurrentSessionId(filtered[0].id);
153+
} else {
154+
setCurrentSessionId(null);
155+
}
156+
}
157+
158+
return filtered;
159+
});
160+
}, [currentSessionId]);
161+
162+
const addMessageToCurrentSession = useCallback((message: ChatMessage) => {
163+
if (!currentSessionId) {
164+
return;
165+
}
166+
167+
setSessions(prev => prev.map(session => {
168+
if (session.id === currentSessionId) {
169+
return {
170+
...session,
171+
messages: [...session.messages, message],
172+
updatedAt: new Date().toISOString(),
173+
};
174+
}
175+
return session;
176+
}));
177+
}, [currentSessionId]);
178+
179+
const updateMessageInCurrentSession = useCallback((messageId: number, updatedMessage: ChatMessage) => {
180+
if (!currentSessionId) {
181+
return;
182+
}
183+
184+
setSessions(prev => prev.map(session => {
185+
if (session.id === currentSessionId) {
186+
return {
187+
...session,
188+
messages: session.messages.map(msg => {
189+
return msg.id === messageId ? updatedMessage : msg;
190+
}),
191+
updatedAt: new Date().toISOString(),
192+
};
193+
}
194+
return session;
195+
}));
196+
}, [currentSessionId]);
197+
198+
const updateSessionTitle = useCallback((sessionId: string, title: string) => {
199+
setSessions(prev => prev.map(session => {
200+
if (session.id === sessionId) {
201+
return {
202+
...session,
203+
title,
204+
updatedAt: new Date().toISOString(),
205+
};
206+
}
207+
return session;
208+
}));
209+
}, []);
210+
211+
const clearAllSessions = useCallback(() => {
212+
setSessions([]);
213+
setCurrentSessionId(null);
214+
// Clear localStorage as well
215+
try {
216+
localStorage.removeItem(STORAGE_KEY);
217+
localStorage.removeItem(CURRENT_SESSION_KEY);
218+
} catch (error) {
219+
// Silently handle localStorage errors
220+
}
221+
}, []);
222+
223+
const value: ChatSessionContextType = {
224+
sessions,
225+
currentSessionId,
226+
currentSession,
227+
createNewSession,
228+
switchSession,
229+
deleteSession,
230+
addMessageToCurrentSession,
231+
updateMessageInCurrentSession,
232+
updateSessionTitle,
233+
clearAllSessions,
234+
};
235+
236+
return (
237+
<ChatSessionContext.Provider value={value}>
238+
{children}
239+
</ChatSessionContext.Provider>
240+
);
241+
};

0 commit comments

Comments
 (0)