-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/f 57 render ai response in markdown #20
Conversation
✅ Deploy Preview for wfp-hungermap ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
b41ae3c
to
ce0ebea
Compare
src/components/Chatbot/Chatbot.tsx
Outdated
const startNewChat = (): void => { | ||
const newChat: IChat = { id: chats.length + 1, title: `Chat ${chats.length + 1}`, messages: [] }; | ||
setChats([...chats, newChat]); | ||
setCurrentChatIndex(chats.length); | ||
if (isMobile) { | ||
setIsSidebarOpen(false); | ||
if (isResponseAnimated) { | ||
const newChat: IChat = { id: chats.length + 1, title: `Chat ${chats.length + 1}`, messages: [], isTyping: false }; | ||
setChats([...chats, newChat]); | ||
setCurrentChatIndex(chats.length); | ||
if (isMobile) { | ||
setIsSidebarOpen(false); | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting a new chat is not working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done generally. Code Refactoring is necessary, because at first look I didn't get the code and its structure, especially with all the complex typing functions, chats etc. Additionally the newChat button is not working. Please revisit and refactor the code a bi + fix the errors in functionality. Generally I think that the job is well done in terms of functionality, but its execution should also be good in terms of quality and maintainablity
src/components/Chatbot/Chatbot.tsx
Outdated
const setTypingStatus = async (chatIndex: number, isTyping: boolean): Promise<void> => { | ||
return new Promise((resolve) => { | ||
setChats((prevChats) => prevChats.map((chat, index) => (index === chatIndex ? { ...chat, isTyping } : chat))); | ||
resolve(); | ||
}); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason why this is a promise?
src/components/Chatbot/Chatbot.tsx
Outdated
@@ -115,26 +125,33 @@ export default function HungerMapChatbot() { | |||
* @param promptText is requested text from user | |||
*/ | |||
const handleSubmit = (fromEvent: React.FormEvent, promptText: string | null = null): void => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is fromEvent
=> precise naming
src/components/Chatbot/Chatbot.tsx
Outdated
fromEvent.preventDefault(); | ||
const text = promptText || input; | ||
chats[currentChatIndex].isTyping = true; | ||
if (text.trim()) { | ||
const updatedChats = structuredClone(chats); | ||
updatedChats[currentChatIndex].messages.push({ id: crypto.randomUUID(), content: text, role: SenderRole.USER }); | ||
if (updatedChats[currentChatIndex].title === `Chat ${updatedChats[currentChatIndex].id}`) { | ||
updatedChats[currentChatIndex].title = text.slice(0, 30) + (text.length > 30 ? '...' : ''); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire thing has nothing to do with the component => should go into an operations file
src/components/Chatbot/Chatbot.tsx
Outdated
// use to scroll to the end of the chat when new messages are added | ||
useEffect(() => { | ||
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); | ||
}, [chats, currentChatIndex]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work as well. So when the message exceedes the chatbox window we should scroll
src/components/Chatbot/Chatbot.tsx
Outdated
onTypingComplete={() => { | ||
handleTypingComplete(); | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
() => handleTypingComplete
no {}
const markdownComponents: Components = { | ||
h1: ({ children, ...props }) => ( | ||
<h1 className="text-xl sm:text-2xl md:text-3xl font-bold mb-2" {...props}> | ||
{children} | ||
</h1> | ||
), | ||
|
||
h2: ({ children, ...props }) => ( | ||
<h2 className="text-lg sm:text-xl md:text-2xl font-bold mb-2 mt-0" {...props}> | ||
{children} | ||
</h2> | ||
), | ||
|
||
h3: ({ children, ...props }) => ( | ||
<h3 className="text-base sm:text-lg md:text-xl font-bold mb-1" {...props}> | ||
{children} | ||
</h3> | ||
), | ||
|
||
p: ({ children, ...props }) => ( | ||
<p className="text-sm sm:text-base my-2 leading-relaxed" {...props}> | ||
{children} | ||
</p> | ||
), | ||
|
||
ul: ({ children, ...props }) => ( | ||
<ul className="list-disc pl-2 sm:pl-4 my-2 space-y-1 text-sm sm:text-base" {...props}> | ||
{children} | ||
</ul> | ||
), | ||
|
||
ol: ({ children, ...props }) => ( | ||
<ol className="list-decimal pl-2 sm:pl-4 my-2 space-y-1 text-sm sm:text-base" {...props}> | ||
{children} | ||
</ol> | ||
), | ||
|
||
li: ({ children, ...props }) => ( | ||
<li className="ml-2" {...props}> | ||
{children} | ||
</li> | ||
), | ||
|
||
blockquote: ({ children, ...props }) => ( | ||
<blockquote | ||
className="border-l-4 border-gray-300 dark:border-gray-700 pl-2 sm:pl-3 my-2 italic text-sm sm:text-base" | ||
{...props} | ||
> | ||
{children} | ||
</blockquote> | ||
), | ||
|
||
// may be removed later since code rendering not supported | ||
code: ({ children, ...props }) => ( | ||
<code className="bg-gray-100 dark:bg-gray-800 rounded px-1 py-0.5 font-mono text-xs sm:text-sm" {...props}> | ||
{children} | ||
</code> | ||
), | ||
|
||
a: ({ children, href, ...props }) => ( | ||
<a | ||
href={href} | ||
className="text-brand hover:text-brandHover underline text-sm sm:text-base" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
{...props} | ||
> | ||
{children} | ||
</a> | ||
), | ||
|
||
hr: (props) => <hr className="my-4 border-gray-300 dark:border-gray-700" {...props} />, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract this into a separate file
* sets isTyping to false so that dot animation | ||
* gets cancelled | ||
*/ | ||
const handleTypingStart = async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return type of the function
/** | ||
* Handles typing animation completion | ||
*/ | ||
const handleTypingComplete = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function return type
/** | ||
* Restores typing progress from localStorage | ||
*/ | ||
const restoreProgress = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return type of the function + this function could be extracted into operations file
const animateText = () => { | ||
if (currentIndex < normalizedText.length) { | ||
const delay = calculateDelay(currentIndex); | ||
setDisplayedText(normalizedText.slice(0, currentIndex + 1)); | ||
|
||
// Save progress | ||
const progress: TypingProgress = { | ||
index: currentIndex + 1, | ||
timestamp: Date.now(), | ||
}; | ||
localStorage.setItem(progressKey, JSON.stringify(progress)); | ||
|
||
currentIndex += 1; | ||
setTimeout(animateText, delay); | ||
} else { | ||
handleTypingComplete(); | ||
} | ||
}; | ||
|
||
handleTypingStart(); | ||
|
||
// Check if animation is already completed | ||
if (localStorage.getItem(completionKey) === 'true') { | ||
setDisplayedText(normalizedText); | ||
} else { | ||
// Restore progress and continue animation | ||
currentIndex = restoreProgress(); | ||
setDisplayedText(normalizedText.slice(0, currentIndex)); | ||
|
||
if (currentIndex < normalizedText.length) { | ||
animateText(); | ||
} else { | ||
handleTypingComplete(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid having such long functions. This should be split into simple, easy to understand functions
function orderPizza(): void {
unlockPhone()
chooseResaurant()
chooseMeal()
orderMeal()
payMeal()
closePhone()
}
And not
function orderPizza(): void {
phone.password = 'PizzePizza'
phone.faceUnlock = true
phone.unlocking = true
phone.unlocked = false
try {
phone.forceUnlock
}
etcetctc.....
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done generally. Code Refactoring is necessary, because at first look I didn't get the code and its structure, especially with all the complex typing functions, chats etc. Additionally the newChat button is not working. Please revisit and refactor the code a bi + fix the errors in functionality. Generally I think that the job is well done in terms of functionality, but its execution should also be good in terms of quality and maintainablity
…i-response-in-markdown
…/github.com/jst-seminar-rostlab-tum/wfp-hunger-map into feature/f-57-render-ai-response-in-markdown
…i-response-in-markdown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I see the improvement in code quality already and there is no single place where I can say something. I'm happy that you are learning in the most perfect way possible. Awesome job Ahmet!
- headings (h1, h2, h3)
- bold text
- bullet points
- ordered lists
- blockquotes
- url
- strikethrough
- tables
- tasklists
Edit: