diff --git a/Frontend/src/components/chat/QuickRefineToolbar.tsx b/Frontend/src/components/chat/QuickRefineToolbar.tsx new file mode 100644 index 0000000..42a20ec --- /dev/null +++ b/Frontend/src/components/chat/QuickRefineToolbar.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { Scissors, Briefcase, List, RotateCcw } from "lucide-react"; + +interface QuickRefineToolbarProps { + onRefine: (prompt: string) => void; +} + +const QuickRefineToolbar: React.FC = ({ onRefine }) => { + const actions = [ + { + id: "shorten", + label: "Shorten", + icon: , + prompt: "Summarize the previous response to be much shorter." + }, + { + id: "pro", + label: "Professional", + icon: , + prompt: "Rewrite the previous response in a professional, formal tone." + }, + { + id: "list", + label: "Listify", + icon: , + prompt: "Convert the previous response into a bulleted list." + }, + { + id: "retry", + label: "Retry", + icon: , + prompt: "Regenerate the previous response." + }, + ]; + + return ( +
+ {actions.map((action) => ( + + ))} +
+ ); +}; + +export default QuickRefineToolbar; \ No newline at end of file diff --git a/Frontend/src/components/chat/message-item.tsx b/Frontend/src/components/chat/message-item.tsx index 3082604..8fa1083 100644 --- a/Frontend/src/components/chat/message-item.tsx +++ b/Frontend/src/components/chat/message-item.tsx @@ -1,15 +1,21 @@ import { type Message } from "@/redux/chatSlice"; import { CheckCheckIcon, CheckIcon } from "lucide-react"; - import React from "react"; +import QuickRefineToolbar from "./QuickRefineToolbar"; + +interface MessageItemProps { + message: Message; + onSendMessage?: (msg: string) => void; +} -export default function MessageItem({ message }: { message: Message }) { +export default function MessageItem({ message, onSendMessage }: MessageItemProps) { return ( <> {message.isSent ? ( -
-
-

{message.message}

+ /* User Messages */ +
+
+

{message.message}

{new Date(message.createdAt).toLocaleTimeString([], { @@ -17,39 +23,39 @@ export default function MessageItem({ message }: { message: Message }) { minute: "2-digit", })} - {message.status === "sent" && ( - - - - )} + {message.status === "sent" && } {message.status === "delivered" && ( - - - + )} {message.status === "seen" && ( - - - + )}
) : ( -
-
-

{message.message}

-
- - {new Date(message.createdAt).toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - })} - + /* AI Messages - Added 'group' for hover logic */ +
+
+
+

{message.message}

+
+ + {new Date(message.createdAt).toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + })} + +
+ + {/* Toolbar only appears for AI responses on hover */} + {onSendMessage && ( + + )}
)} ); -} +} \ No newline at end of file diff --git a/Frontend/src/components/chat/messages-list.tsx b/Frontend/src/components/chat/messages-list.tsx index 429b529..4086c8b 100644 --- a/Frontend/src/components/chat/messages-list.tsx +++ b/Frontend/src/components/chat/messages-list.tsx @@ -14,12 +14,12 @@ export default function MessagesList({ messages }: { messages: Message[] }) { (state: RootState) => state.chat.selectedChatId ); + const { markMessageAsSeen, sendMessage } = useChat(); + useEffect(() => { setLastMarkedAsSeen(new Date().toISOString()); }, [selectedChatId]); - const { markMessageAsSeen } = useChat(); - useEffect(() => { const unseenMessages = messages.filter( (message) => @@ -33,56 +33,43 @@ export default function MessagesList({ messages }: { messages: Message[] }) { }); setLastMarkedAsSeen(new Date().toISOString()); } - }, [messages]); + }, [messages, lastMarkedAsSeen, markMessageAsSeen]); return ( - <> +
{messages.length > 0 ? ( <> {messages.reduce((acc: JSX.Element[], message, index, array) => { - // Add date separator for first message + // Date Separator Logic + const messageDate = parseISO(message.createdAt); if (index === 0) { - const firstDate = parseISO(message.createdAt); acc.push( -
+
- {format(firstDate, "PPP")} + {format(messageDate, "PPP")}
); } - // Add the message component - acc.push(); + // Push Message Item + acc.push( + + ); - // Check if the next message is from a different date + // Date separator for subsequent messages if (index < array.length - 1) { - const currentDate = parseISO(message.createdAt); const nextDate = parseISO(array[index + 1].createdAt); - - // Check if dates are different - if ( - !isEqual( - new Date( - currentDate.getFullYear(), - currentDate.getMonth(), - currentDate.getDate() - ), - new Date( - nextDate.getFullYear(), - nextDate.getMonth(), - nextDate.getDate() - ) - ) - ) { + if (!isEqual( + new Date(messageDate.setHours(0,0,0,0)), + new Date(nextDate.setHours(0,0,0,0)) + )) { acc.push( -
+
{format(nextDate, "PPP")}
@@ -95,10 +82,10 @@ export default function MessagesList({ messages }: { messages: Message[] }) { }, [])} ) : ( -
-

No messages yet

+
+

No messages yet. Start a conversation!

)} - +
); -} +} \ No newline at end of file diff --git a/Frontend/src/components/ui/input.tsx b/Frontend/src/components/ui/input.tsx index 6ed9422..48a6e75 100644 --- a/Frontend/src/components/ui/input.tsx +++ b/Frontend/src/components/ui/input.tsx @@ -1,7 +1,10 @@ -import React from "react"; -import { cn } from "../../lib/utils"; +import * as React from "react"; +import { cn } from "@/lib/utils"; -const Input = React.forwardRef>( +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( ({ className, type, ...props }, ref) => { return ( >( ); Input.displayName = "Input"; -export { Input }; +export { Input }; \ No newline at end of file diff --git a/Frontend/src/index.css b/Frontend/src/index.css index f2a93bb..4f3bce8 100644 --- a/Frontend/src/index.css +++ b/Frontend/src/index.css @@ -117,37 +117,23 @@ body { @apply bg-background text-foreground; } -} + /* Custom Animations */ @keyframes gradient { - 0% { - background-position: 0% 50%; - } - 50% { - background-position: 100% 50%; - } - 100% { - background-position: 0% 50%; - } + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } } @keyframes float { - 0%, 100% { - transform: translateY(0px); - } - 50% { - transform: translateY(-10px); - } + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-10px); } } @keyframes glow { - 0%, 100% { - box-shadow: 0 0 20px rgba(147, 51, 234, 0.3); - } - 50% { - box-shadow: 0 0 40px rgba(147, 51, 234, 0.6); - } + 0%, 100% { box-shadow: 0 0 20px rgba(147, 51, 234, 0.3); } + 50% { box-shadow: 0 0 40px rgba(147, 51, 234, 0.6); } } .animate-gradient {