Skip to content

Commit

Permalink
Merge pull request #43 from jamakase/feature/front-basement
Browse files Browse the repository at this point in the history
Feature/front basement
  • Loading branch information
FanisNgv authored Sep 12, 2024
2 parents adda5b0 + 6a7fe94 commit 7abeeec
Show file tree
Hide file tree
Showing 4 changed files with 379 additions and 325 deletions.
2 changes: 1 addition & 1 deletion frontend/src/app/components/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type MessageListProps = {

export default function MessageList({ messages }: MessageListProps) {
return (
<ScrollArea className="flex-1 p-4 overflow-y-auto bg-white">
<ScrollArea key={messages.length} className="flex-1 p-4 overflow-y-auto bg-white">
<AnimatePresence>
{messages.map((msg) => (
<motion.div
Expand Down
132 changes: 79 additions & 53 deletions frontend/src/app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useRef } from 'react';
import React, { useRef, useCallback } from 'react';
import Link from 'next/link';
import { motion, AnimatePresence } from 'framer-motion';
import { Button } from "@/components/ui/button"


type Conversation = {
id: number;
name: string;
messages: Array<{ id: number; text: string; sender: string }>};
messages: Array<{ id: number; text: string; sender: string }>;
};

type SidebarProps = {
conversations: Conversation[];
Expand All @@ -19,9 +19,79 @@ type SidebarProps = {
onCloseSidebar: () => void;
};

type ConversationItemProps = {
conversation: Conversation;
isActive: boolean;
onConversationChange: (id: number) => void;
onDeleteConversation: (id: number) => void;
};

const ConversationItem = React.memo(({ conversation, isActive, onConversationChange, onDeleteConversation }: ConversationItemProps) => {
return (
<motion.div
layout
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{
duration: 0.3,
ease: "easeInOut",
opacity: { duration: 0.2 },
scale: { duration: 0.2 },
layout: { duration: 0.3 }
}}
>
<Link
href={`/conversations/${conversation.id}`}
onClick={(e) => {
e.preventDefault();
onConversationChange(conversation.id);
}}
>
<label
htmlFor={`chat-${conversation.id}`}
className={`flex text-base mb-4 cursor-pointer items-center justify-between gap-4 rounded-lg border p-4 text-sm font-medium shadow-sm hover:border-[#E5A7ED] ${
isActive
? 'bg-[#D988E4] text-black'
: 'bg-[#E6E8EF] text-black'
}`}
>
<p>{conversation.name}</p>
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onDeleteConversation(conversation.id);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 -960 960 960"
width="24"
fill="#898D9F"
className="hover:fill-[#E5A7ED]"
>
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/>
</svg>
</button>
</label>
</Link>
</motion.div>
);
});

export default function Sidebar({ conversations, currentConversationId, onConversationChange, onAddConversation, onDeleteConversation, isSidebarOpen, onCloseSidebar }: SidebarProps) {
const menuRef = useRef(null);

const handleConversationChange = useCallback((id: number) => {
onConversationChange(id);
}, [onConversationChange]);

const handleDeleteConversation = useCallback((id: number) => {
onDeleteConversation(id);
}, [onDeleteConversation]);

return (
<aside
ref={menuRef}
Expand Down Expand Up @@ -64,57 +134,13 @@ export default function Sidebar({ conversations, currentConversationId, onConver
<fieldset className="space-y-4">
<AnimatePresence mode="popLayout">
{conversations.map((conversation) => (
<motion.div
<ConversationItem
key={conversation.id}
layout
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{
duration: 0.3,
ease: "easeInOut",
opacity: { duration: 0.2 },
scale: { duration: 0.2 },
layout: { duration: 0.3 }
}}
>
<Link
href={`/${conversation.id}`}
onClick={(e) => {
e.preventDefault();
onConversationChange(conversation.id);
}}
>
<label
htmlFor={`chat-${conversation.id}`}
className={`flex text-base mb-4 cursor-pointer items-center justify-between gap-4 rounded-lg border p-4 text-sm font-medium shadow-sm hover:border-[#E5A7ED] ${
currentConversationId === conversation.id
? 'bg-[#D988E4] text-black'
: 'bg-[#E6E8EF] text-black'
}`}
>
<p>{conversation.name}</p>
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onDeleteConversation(conversation.id);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 -960 960 960"
width="24"
fill="#898D9F"
className="hover:fill-[#E5A7ED]"
>
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/>
</svg>
</button>
</label>
</Link>
</motion.div>
conversation={conversation}
isActive={currentConversationId === conversation.id}
onConversationChange={handleConversationChange}
onDeleteConversation={handleDeleteConversation}
/>
))}
</AnimatePresence>
</fieldset>
Expand Down
Loading

0 comments on commit 7abeeec

Please sign in to comment.