diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index ad9d72a..4454094 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -18,9 +18,7 @@ export default function App() {
diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx
index e065d65..7a55cd0 100644
--- a/frontend/src/Navigation.tsx
+++ b/frontend/src/Navigation.tsx
@@ -32,6 +32,7 @@ import { useMediaQuery, useOutsideAlerter } from './hooks';
import Upload from './upload/Upload';
import { Doc, getConversations } from './preferences/preferenceApi';
import SelectDocsModal from './preferences/SelectDocsModal';
+import ConversationTile from './conversation/ConversationTile';
interface NavigationProps {
navOpen: boolean;
@@ -68,16 +69,20 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
useEffect(() => {
if (!conversations) {
- getConversations()
- .then((fetchedConversations) => {
- dispatch(setConversations(fetchedConversations));
- })
- .catch((error) => {
- console.error('Failed to fetch conversations: ', error);
- });
+ fetchConversations();
}
}, [conversations, dispatch]);
+ async function fetchConversations() {
+ return await getConversations()
+ .then((fetchedConversations) => {
+ dispatch(setConversations(fetchedConversations));
+ })
+ .catch((error) => {
+ console.error('Failed to fetch conversations: ', error);
+ });
+ }
+
const handleDeleteConversation = (id: string) => {
fetch(`${apiHost}/api/delete_conversation?id=${id}`, {
method: 'POST',
@@ -89,6 +94,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
) as HTMLElement;
const parentElement = imageElement.parentNode as HTMLElement;
parentElement.parentNode?.removeChild(parentElement);
+ fetchConversations();
})
.catch((error) => console.error(error));
};
@@ -126,6 +132,29 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
);
});
};
+
+ async function updateConversationName(updatedConversation: {
+ name: string;
+ id: string;
+ }) {
+ await fetch(`${apiHost}/api/update_conversation_name`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(updatedConversation),
+ })
+ .then((response) => response.json())
+ .then((data) => {
+ if (data) {
+ navigate('/');
+ fetchConversations();
+ }
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ }
useOutsideAlerter(
navRef,
() => {
@@ -210,41 +239,17 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
{conversations
- ? conversations.map((conversation) => {
- return (
-
{
- handleConversationClick(conversation.id);
- }}
- className={`my-auto mx-4 mt-4 flex h-12 cursor-pointer items-center justify-between gap-4 rounded-3xl hover:bg-gray-100 ${
- conversationId === conversation.id ? 'bg-gray-100' : ''
- }`}
- >
-
-
-
- {conversation.name.length > 45
- ? conversation.name.substring(0, 45) + '...'
- : conversation.name}
-
-
-
- {conversationId === conversation.id ? (
-
{
- event.stopPropagation();
- handleDeleteConversation(conversation.id);
- }}
- />
- ) : null}
-
- );
- })
+ ? conversations.map((conversation, index) => (
+
handleConversationClick(id)}
+ onDeleteConversation={(id) => handleDeleteConversation(id)}
+ onSave={(conversation) =>
+ updateConversationName(conversation)
+ }
+ />
+ ))
: null}
diff --git a/frontend/src/assets/checkMark.svg b/frontend/src/assets/checkMark.svg
new file mode 100644
index 0000000..9ed02cb
--- /dev/null
+++ b/frontend/src/assets/checkMark.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/checkmark.svg b/frontend/src/assets/checkmark.svg
index 682c29d..9ed02cb 100644
--- a/frontend/src/assets/checkmark.svg
+++ b/frontend/src/assets/checkmark.svg
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file
diff --git a/frontend/src/assets/edit.svg b/frontend/src/assets/edit.svg
new file mode 100644
index 0000000..2565377
--- /dev/null
+++ b/frontend/src/assets/edit.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/trash.svg b/frontend/src/assets/trash.svg
new file mode 100644
index 0000000..d0e4546
--- /dev/null
+++ b/frontend/src/assets/trash.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/frontend/src/conversation/ConversationTile.tsx b/frontend/src/conversation/ConversationTile.tsx
new file mode 100644
index 0000000..592c52b
--- /dev/null
+++ b/frontend/src/conversation/ConversationTile.tsx
@@ -0,0 +1,128 @@
+import { useEffect, useRef, useState } from 'react';
+import { useSelector } from 'react-redux';
+import Edit from '../assets/edit.svg';
+import Exit from '../assets/exit.svg';
+import Message from '../assets/message.svg';
+import CheckMark from '../assets/checkmark.svg';
+import Trash from '../assets/trash.svg';
+
+import { selectConversationId } from '../preferences/preferenceSlice';
+import { useOutsideAlerter } from '../hooks';
+
+interface ConversationProps {
+ name: string;
+ id: string;
+}
+interface ConversationTileProps {
+ conversation: ConversationProps;
+ selectConversation: (arg1: string) => void;
+ onDeleteConversation: (arg1: string) => void;
+ onSave: ({ name, id }: ConversationProps) => void;
+}
+
+export default function ConversationTile({
+ conversation,
+ selectConversation,
+ onDeleteConversation,
+ onSave,
+}: ConversationTileProps) {
+ const conversationId = useSelector(selectConversationId);
+ const tileRef = useRef
(null);
+
+ const [isEdit, setIsEdit] = useState(false);
+ const [conversationName, setConversationsName] = useState('');
+ useOutsideAlerter(
+ tileRef,
+ () =>
+ handleSaveConversation({
+ id: conversationId || conversation.id,
+ name: conversationName,
+ }),
+ [conversationName],
+ );
+
+ useEffect(() => {
+ setConversationsName(conversation.name);
+ }, [conversation.name]);
+
+ function handleEditConversation() {
+ setIsEdit(true);
+ }
+
+ function handleSaveConversation(changedConversation: ConversationProps) {
+ if (changedConversation.name.trim().length) {
+ onSave(changedConversation);
+ setIsEdit(false);
+ } else {
+ onClear();
+ }
+ }
+
+ function onClear() {
+ setConversationsName(conversation.name);
+ setIsEdit(false);
+ }
+ return (
+ {
+ selectConversation(conversation.id);
+ }}
+ className={`my-auto mx-4 mt-4 flex h-12 cursor-pointer items-center justify-between gap-4 rounded-3xl hover:bg-gray-100 ${
+ conversationId === conversation.id ? 'bg-gray-100' : ''
+ }`}
+ >
+
+
+ {isEdit ? (
+
setConversationsName(e.target.value)}
+ />
+ ) : (
+
+ {conversationName}
+
+ )}
+
+ {conversationId === conversation.id ? (
+
+
{
+ event.stopPropagation();
+ isEdit
+ ? handleSaveConversation({
+ id: conversationId,
+ name: conversationName,
+ })
+ : handleEditConversation();
+ }}
+ />
+
{
+ event.stopPropagation();
+ isEdit ? onClear() : onDeleteConversation(conversation.id);
+ }}
+ />
+
+ ) : null}
+
+ );
+}