looood / src /components /chat /chat-layout.tsx
looda3131's picture
Clean push without any binary history
cc276cc
'use client';
import React, { useState, useEffect } from 'react';
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable';
import { cn } from '@/lib/utils';
import { Chat } from '@/lib/types';
import { ChatList } from './chat-list';
import { Message, UserData } from '@/lib/types';
import { MessageList } from './message-list';
import { MessageInput } from '../message-input';
import { ChatTopbar } from './chat-topbar';
import { Sidebar } from './sidebar';
interface ChatLayoutProps {
defaultLayout: number[] | undefined;
navCollapsedSize: number;
chats: Chat[];
loggedInUser: UserData;
}
export function ChatLayout({
defaultLayout = [320, 1080],
navCollapsedSize,
chats: initialChats,
loggedInUser,
}: ChatLayoutProps) {
const [isCollapsed, setIsCollapsed] = React.useState(false);
const [selectedChat, setSelectedChat] = React.useState<Chat | null>(initialChats[0]);
const [isMobile, setIsMobile] = useState(false);
const [chats, setChats] = useState(initialChats);
const [isTyping, setIsTyping] = useState(false);
useEffect(() => {
const checkScreenWidth = () => {
setIsMobile(window.innerWidth <= 768);
};
checkScreenWidth();
window.addEventListener('resize', checkScreenWidth);
return () => {
window.removeEventListener('resize', checkScreenWidth);
};
}, []);
const handleSendMessage = async (newMessageText: string) => {
if (!selectedChat) return;
setIsTyping(true);
const themedResponse = { theme: undefined };
const newMessage: Message = {
id: `msg-${Date.now()}`,
sender: loggedInUser,
text: newMessageText,
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
theme: themedResponse.theme,
};
// Simulate a response
setTimeout(() => {
const otherUser = selectedChat.users.find(u => u.id !== loggedInUser.id);
if (otherUser) {
const responseMessage: Message = {
id: `msg-${Date.now() + 1}`,
sender: otherUser,
text: `This is an automatic reply to: "${newMessageText}"`,
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
};
setChats(prevChats =>
prevChats.map(chat =>
chat.id === selectedChat.id
? { ...chat, messages: [...chat.messages, newMessage, responseMessage] }
: chat
)
);
}
setIsTyping(false);
}, 1500);
setChats(prevChats =>
prevChats.map(chat =>
chat.id === selectedChat.id
? { ...chat, messages: [...chat.messages, newMessage] }
: chat
)
);
};
const currentChat = chats.find(c => c.id === selectedChat?.id);
return (
<div className="flex h-screen w-full">
<Sidebar isCollapsed={isCollapsed || isMobile} loggedInUser={loggedInUser} />
<div className="flex-1">
{isMobile ? (
<div className="flex h-full w-full">
{!selectedChat ? (
<ChatList
chats={chats}
selectedChat={selectedChat}
onSelectChat={setSelectedChat}
isMobile={isMobile}
loggedInUser={loggedInUser}
/>
) : (
<div className="flex flex-col w-full h-full">
<ChatTopbar selectedChat={selectedChat} onBack={() => setSelectedChat(null)} />
<MessageList
messages={currentChat?.messages ?? []}
loggedInUser={loggedInUser}
isTyping={isTyping}
/>
{/* @ts-ignore */}
<MessageInput onSendMessage={handleSendMessage} />
</div>
)}
</div>
) : (
<ResizablePanelGroup
direction="horizontal"
onLayout={(sizes: number[]) => {
document.cookie = `react-resizable-panels:layout=${JSON.stringify(
sizes
)}`;
}}
className="h-full items-stretch"
>
<ResizablePanel
defaultSize={defaultLayout[0]}
collapsedSize={navCollapsedSize}
collapsible={true}
minSize={15}
maxSize={25}
onCollapse={() => {
setIsCollapsed(true);
document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(
true
)}`;
}}
onExpand={() => {
setIsCollapsed(false);
document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(
false
)}`;
}}
className={cn(
isCollapsed &&
'min-w-[50px] transition-all duration-300 ease-in-out'
)}
>
<ChatList
isCollapsed={isCollapsed}
chats={chats}
selectedChat={selectedChat}
onSelectChat={setSelectedChat}
loggedInUser={loggedInUser}
/>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={defaultLayout[1]} minSize={30}>
{selectedChat ? (
<div className="flex flex-col h-full">
<ChatTopbar selectedChat={selectedChat} />
<MessageList
messages={currentChat?.messages ?? []}
loggedInUser={loggedInUser}
isTyping={isTyping}
/>
{/* @ts-ignore */}
<MessageInput onSendMessage={handleSendMessage} />
</div>
) : (
<div className="flex h-full items-center justify-center bg-muted/50">
<div className="text-center">
<h2 className="text-2xl font-bold">Select a chat to start messaging</h2>
<p className="text-muted-foreground">Your conversations will appear here.</p>
</div>
</div>
)}
</ResizablePanel>
</ResizablePanelGroup>
)}
</div>
</div>
);
}