Design a WhatsApp-style chat interface, like the one attached in the picture, with three main vertical sections using TailwindCSS, Next.js App Router, and TypeScript.
🔹 Layout requirements: Left Sidebar (Navigation + Chats) Top section:
Search input field
“Custom Filter” button with a save icon and filter badge
Below: List of chat previews (chats prop)
Chat preview includes:
Avatar/logo
Chat title
Last message preview (truncate text)
Timestamp (e.g., "25-Feb-25")
Optional labels: "Demo", "Signup", "Internal", "Content"
Subdued phone number/info text
Footer section:
Left-aligned vertical nav bar with icons (home, chat, users, settings)
Center Pane (Active Chat Window) Header:
Chat title
Participant names (comma-separated)
Avatars for online users
Action icons: refresh, help, search
Scrollable chat body (messages prop):
Left/right aligned message bubbles
Show sender name, timestamp inside message
Show date dividers (e.g., “22-01-2025”)
Input section:
Input field (placeholder: “Message…”)
Icons: emoji, attachment, send
Right Sidebar (Optional Tools) Right-aligned vertical sidebar (mirroring the left nav)
Show icons vertically (e.g., analytics, files, notes)
🛠 Technical Requirements: Use Next.js 14 App Router with TypeScript
Use TailwindCSS only (no external CSS or styled-components)
Use semantic HTML: <nav>, <aside>, <main>, <section>, etc.
Leave placeholders for dynamic logic:
{chats.map(...)}
{messages.map(...)}
onSendMessage()
📦 Output Requirements: Output a clean React component file (or multiple if needed)
Use realistic placeholder data (no lorem ipsum)
No interactivity/state logic — just the structure + styling
Use clear Tailwind classes to match WhatsApp look
Loading...
Loading...
Copy code app/ │ ├── layout.tsx ├── page.tsx ← Root page │ ├── components/ │ ├── Sidebar.tsx ← Left nav + chat list │ ├── ChatList.tsx │ ├── ChatWindow.tsx │ ├── ChatHeader.tsx │ ├── ChatMessages.tsx │ └── ChatInput.tsx │ ├── lib/ │ └── supabaseClient.ts ← Init Supabase │ └── chatService.ts ← All Supabase queries here │ └── types/ └── index.ts ← Chat, Message, User types (use Zod if needed) 2. 🔌 Integrate Supabase In lib/supabaseClient.ts:
ts Copy code import { createClient } from '@supabase/supabase-js'
export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ) Add .env.local:
env Copy code NEXT_PUBLIC_SUPABASE_URL=https://xyz.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key 3. 📦 Build Supabase Query Functions In lib/chatService.ts:
ts Copy code import { supabase } from './supabaseClient'
// Get chats for a user
export async function getUserChats(userId: string) {
const { data, error } = await supabase
.from('chat_participants')
.select(chat_id, chats(id, title, updated_at, chat_participants(user_id, users(username)))
)
.eq('user_id', userId)
if (error) throw error
// Format as needed return data }
// Get messages export async function getMessages(chatId: string) { const { data, error } = await supabase .from('messages') .select('*, users!messages_sender_id_fkey(username)') .eq('chat_id', chatId) .order('created_at', { ascending: true })
if (error) throw error
return data }
// Send a message export async function sendMessage(chatId: string, senderId: string, content: string) { const { error } = await supabase.from('messages').insert({ chat_id: chatId, sender_id: senderId, content })
if (error) throw error } 4. ⚙️ Connect UI to Data (Minimal State) Use useEffect() in ChatList.tsx and ChatMessages.tsx to:
Fetch chats → highlight active chat
Fetch messages → scroll to bottom
Use useState minimally to manage:
currentChatId
currentUserId (from Supabase auth.getUser())
Use supabase.auth.getUser() in a layout effect to get the logged-in user ID.
ts
Copy code
supabase
.channel(chat-${chatId}
)
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: chat_id=eq.${chatId}
}, payload => {
// Append to message state
})
.subscribe()