Frontend: Complete Next.js implementation
Core Features: - ✅ Authentication (login/register pages) - ✅ Main layout with sidebar - ✅ Channel list and navigation - ✅ Channel page with real-time messaging - ✅ Direct messages (DMs) page - ✅ Message components (list, input) - ✅ WebSocket integration for real-time updates - ✅ Typing indicators - ✅ Online status indicators - ✅ Stores (auth, channels, messages) - ✅ API client with JWT auth - ✅ Socket.IO client wrapper - ✅ Responsive UI with Tailwind Tech Stack: - Next.js 14 (App Router) - TypeScript - TailwindCSS - Socket.IO client - Zustand (state management) - Axios (HTTP client) - date-fns (date formatting) - lucide-react (icons) Build Status: ✅ Successfully compiles Production Ready: ✅ Optimized build generated
This commit is contained in:
82
frontend/src/app/(main)/layout.tsx
Normal file
82
frontend/src/app/(main)/layout.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuthStore } from '@/stores/useAuthStore';
|
||||
import { useChannelStore } from '@/stores/useChannelStore';
|
||||
import { useMessageStore } from '@/stores/useMessageStore';
|
||||
import { wsClient } from '@/lib/socket';
|
||||
import Sidebar from '@/components/sidebar/Sidebar';
|
||||
|
||||
export default function MainLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { isAuthenticated, isLoading, loadUser, user } = useAuthStore();
|
||||
const { loadChannels } = useChannelStore();
|
||||
const { addMessage, addDirectMessage, setUserTyping, setUserStoppedTyping, loadConversations } = useMessageStore();
|
||||
|
||||
useEffect(() => {
|
||||
loadUser();
|
||||
}, [loadUser]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
router.push('/login');
|
||||
}
|
||||
}, [isAuthenticated, isLoading, router]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
loadChannels();
|
||||
loadConversations();
|
||||
|
||||
// Setup WebSocket event handlers
|
||||
wsClient.updateHandlers({
|
||||
onNewMessage: (message) => {
|
||||
addMessage(message.channel_id, message);
|
||||
},
|
||||
onNewDM: (dm) => {
|
||||
addDirectMessage(dm);
|
||||
// Reload conversations to update unread count
|
||||
loadConversations();
|
||||
},
|
||||
onUserTyping: (data) => {
|
||||
if (data.user_id !== user?.id) {
|
||||
setUserTyping(data.channel_id, data.user_id);
|
||||
// Auto-clear typing after 3 seconds
|
||||
setTimeout(() => {
|
||||
setUserStoppedTyping(data.channel_id, data.user_id);
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
onUserStoppedTyping: (data) => {
|
||||
setUserStoppedTyping(data.channel_id, data.user_id);
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [isAuthenticated, loadChannels, loadConversations, addMessage, addDirectMessage, setUserTyping, setUserStoppedTyping, user]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-900">
|
||||
<div className="text-white text-xl">Loading...</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-gray-900 text-white overflow-hidden">
|
||||
<Sidebar />
|
||||
<main className="flex-1 flex flex-col overflow-hidden">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user