{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chat-app1",
  "title": "Dashboard Chat App",
  "description": "",
  "dependencies": [
    "framer-motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/default/blocks/Dashboard/Chat-App1.tsx",
      "content": "\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { motion, AnimatePresence } from \"framer-motion\";\r\nimport { Search, MoreVertical, Send, Plus, Smile, ChevronLeft, Image as ImageIcon, Bell, Edit3, CheckCheck } from \"lucide-react\";\r\n\r\n// Type definitions\r\ninterface Message {\r\n    id: string;\r\n    content: string;\r\n    sender: \"me\" | \"other\";\r\n    timestamp: string;\r\n    type: \"text\" | \"images\";\r\n}\r\n\r\ninterface Contact {\r\n    id: string;\r\n    name: string;\r\n    avatar: string;\r\n    messages: Message[];\r\n}\r\n\r\n// Contact data\r\ninterface ContactData extends Contact {\r\n    tab: \"friends\" | \"groups\";\r\n    online: boolean;\r\n    time: string;\r\n    lastMessage: string;\r\n    unread?: number;\r\n    verified?: boolean;\r\n    lastSeen?: string;\r\n}\r\n\r\nconst contacts: ContactData[] = [\r\n    {\r\n        id: \"1\",\r\n        name: \"Alice Mensah\",\r\n        avatar: \"AM\",\r\n        messages: [\r\n            { id: \"1\", content: \"Hi! How are you?\", sender: \"other\", timestamp: \"14:30\", type: \"text\" },\r\n            { id: \"2\", content: \"Very good, and you?\", sender: \"me\", timestamp: \"14:31\", type: \"text\" },\r\n            { id: \"3\", content: \"Cool! Are we meeting this weekend?\", sender: \"other\", timestamp: \"14:32\", type: \"text\" },\r\n        ],\r\n        tab: \"friends\",\r\n        online: true,\r\n        time: \"14:32\",\r\n        lastMessage: \"Are we meeting this weekend?\",\r\n        unread: 3,\r\n        verified: true,\r\n    },\r\n    {\r\n        id: \"2\",\r\n        name: \"Alex Chen\",\r\n        avatar: \"AC\",\r\n        messages: [\r\n            { id: \"1\", content: \"Project finished? 📁\", sender: \"other\", timestamp: \"13:15\", type: \"text\" },\r\n            { id: \"2\", content: \"Yes, it's done!\", sender: \"me\", timestamp: \"13:16\", type: \"text\" },\r\n        ],\r\n        tab: \"friends\",\r\n        online: true,\r\n        time: \"13:16\",\r\n        lastMessage: \"Yes, it's done!\",\r\n        verified: true,\r\n    },\r\n    {\r\n        id: \"3\",\r\n        name: \"Ivan Goldberg\",\r\n        avatar: \"IG\",\r\n        messages: [\r\n            { id: \"1\", content: \"See you soon!\", sender: \"other\", timestamp: \"12:45\", type: \"text\" },\r\n        ],\r\n        tab: \"friends\",\r\n        online: false,\r\n        time: \"12:45\",\r\n        lastMessage: \"See you soon!\",\r\n        lastSeen: \"2h ago\",\r\n    },\r\n    {\r\n        id: \"4\",\r\n        name: \"Christina Brown\",\r\n        avatar: \"CB\",\r\n        messages: [],\r\n        tab: \"friends\",\r\n        online: false,\r\n        time: \"Yesterday\",\r\n        lastMessage: \"Thanks for everything!\",\r\n    },\r\n    {\r\n        id: \"5\",\r\n        name: \"Frontend Engineers\",\r\n        avatar: \"FE\",\r\n        messages: [],\r\n        tab: \"groups\",\r\n        online: true,\r\n        time: \"11:20\",\r\n        lastMessage: \"You: Cool! 👍\",\r\n        unread: 7,\r\n    },\r\n    {\r\n        id: \"6\",\r\n        name: \"React Mentors\",\r\n        avatar: \"RM\",\r\n        messages: [],\r\n        tab: \"groups\",\r\n        online: true,\r\n        time: \"Yesterday\",\r\n        lastMessage: \"See you at the meeting\",\r\n    },\r\n    {\r\n        id: \"7\",\r\n        name: \"Team Rework\",\r\n        avatar: \"TR\",\r\n        messages: [],\r\n        tab: \"groups\",\r\n        online: false,\r\n        time: \"Monday\",\r\n        lastMessage: \"Good luck!\",\r\n    },\r\n    {\r\n        id: \"8\",\r\n        name: \"Open Ground\",\r\n        avatar: \"OG\",\r\n        messages: [],\r\n        tab: \"groups\",\r\n        online: true,\r\n        time: \"Sunday\",\r\n        lastMessage: \"See you tonight!\",\r\n    },\r\n    {\r\n        id: \"9\",\r\n        name: \"Vera Simpson\",\r\n        avatar: \"VS\",\r\n        messages: [],\r\n        tab: \"friends\",\r\n        online: true,\r\n        time: \"Saturday\",\r\n        lastMessage: \"Great idea!\",\r\n    },\r\n];\r\n\r\nconst avatars: Record<string, string> = {\r\n    AM: \"https://api.dicebear.com/7.x/adventurer/svg?seed=AM\",\r\n    AC: \"https://api.dicebear.com/7.x/adventurer/svg?seed=AC\",\r\n    IG: \"https://api.dicebear.com/7.x/adventurer/svg?seed=IG\",\r\n    CB: \"https://api.dicebear.com/7.x/adventurer/svg?seed=CB\",\r\n    FE: \"https://api.dicebear.com/7.x/adventurer/svg?seed=FE\",\r\n    RM: \"https://api.dicebear.com/7.x/adventurer/svg?seed=RM\",\r\n    TR: \"https://api.dicebear.com/7.x/adventurer/svg?seed=TR\",\r\n    OG: \"https://api.dicebear.com/7.x/adventurer/svg?seed=OG\",\r\n    VS: \"https://api.dicebear.com/7.x/adventurer/svg?seed=VS\",\r\n};\r\n\r\n// Artwork-style placeholder images using SVG data URIs\r\nconst artworkImages = [\r\n    `data:image/svg+xml,${encodeURIComponent(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"200\" height=\"180\" viewBox=\"0 0 200 180\">\r\n    <defs>\r\n      <linearGradient id=\"sky1\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\r\n        <stop offset=\"0%\" style=\"stop-color:#b8d4e8\"/>\r\n        <stop offset=\"100%\" style=\"stop-color:#d4e9c8\"/>\r\n      </linearGradient>\r\n    </defs>\r\n    <rect width=\"200\" height=\"180\" fill=\"url(#sky1)\"/>\r\n    <ellipse cx=\"60\" cy=\"60\" rx=\"35\" ry=\"30\" fill=\"#5a8a3c\" opacity=\"0.8\"/>\r\n    <ellipse cx=\"140\" cy=\"50\" rx=\"28\" ry=\"25\" fill=\"#4a7a2c\" opacity=\"0.9\"/>\r\n    <ellipse cx=\"100\" cy=\"70\" rx=\"20\" ry=\"18\" fill=\"#6a9a4c\" opacity=\"0.7\"/>\r\n    <rect x=\"55\" y=\"85\" width=\"8\" height=\"40\" fill=\"#6b4226\"/>\r\n    <rect x=\"133\" y=\"72\" width=\"6\" height=\"35\" fill=\"#6b4226\"/>\r\n    <rect x=\"0\" y=\"130\" width=\"200\" height=\"50\" fill=\"#8ab866\" opacity=\"0.6\"/>\r\n    <rect x=\"0\" y=\"145\" width=\"200\" height=\"35\" fill=\"#7aa856\" opacity=\"0.5\"/>\r\n    <ellipse cx=\"30\" cy=\"155\" rx=\"25\" ry=\"8\" fill=\"#5a8840\" opacity=\"0.6\"/>\r\n    <ellipse cx=\"170\" cy=\"160\" rx=\"20\" ry=\"6\" fill=\"#4a7830\" opacity=\"0.7\"/>\r\n    <path d=\"M0,140 Q50,125 100,135 Q150,145 200,130\" fill=\"none\" stroke=\"#6a9850\" stroke-width=\"2\" opacity=\"0.4\"/>\r\n  </svg>`)}`,\r\n\r\n    `data:image/svg+xml,${encodeURIComponent(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"200\" height=\"180\" viewBox=\"0 0 200 180\">\r\n    <defs>\r\n      <linearGradient id=\"sky2\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\r\n        <stop offset=\"0%\" style=\"stop-color:#c8dff0\"/>\r\n        <stop offset=\"100%\" style=\"stop-color:#e8d4a8\"/>\r\n      </linearGradient>\r\n    </defs>\r\n    <rect width=\"200\" height=\"180\" fill=\"url(#sky2)\"/>\r\n    <path d=\"M60,100 Q100,30 140,100\" fill=\"#c8a870\" opacity=\"0.3\"/>\r\n    <ellipse cx=\"100\" cy=\"40\" rx=\"40\" ry=\"30\" fill=\"#4a7a3c\" opacity=\"0.7\"/>\r\n    <ellipse cx=\"70\" cy=\"55\" rx=\"25\" ry=\"20\" fill=\"#5a8a4c\" opacity=\"0.8\"/>\r\n    <ellipse cx=\"130\" cy=\"60\" rx=\"22\" ry=\"18\" fill=\"#3a6a2c\" opacity=\"0.9\"/>\r\n    <rect x=\"96\" y=\"68\" width=\"7\" height=\"50\" fill=\"#8b6343\"/>\r\n    <rect x=\"0\" y=\"120\" width=\"200\" height=\"60\" fill=\"#9cbd78\" opacity=\"0.5\"/>\r\n    <rect x=\"0\" y=\"135\" width=\"200\" height=\"45\" fill=\"#8aad68\"/>\r\n    <circle cx=\"50\" cy=\"125\" r=\"15\" fill=\"#6a9d48\" opacity=\"0.6\"/>\r\n    <circle cx=\"155\" cy=\"130\" r=\"12\" fill=\"#5a8d38\" opacity=\"0.7\"/>\r\n    <path d=\"M20,145 Q80,130 160,140 Q180,143 200,138\" fill=\"none\" stroke=\"#7a9d58\" stroke-width=\"3\" opacity=\"0.5\"/>\r\n    <rect x=\"85\" y=\"148\" width=\"30\" height=\"12\" rx=\"3\" fill=\"#c8b890\" opacity=\"0.5\"/>\r\n    <circle cx=\"170\" cy=\"25\" rx=\"18\" ry=\"18\" fill=\"#f8e898\" opacity=\"0.8\"/>\r\n  </svg>`)}`,\r\n\r\n    `data:image/svg+xml,${encodeURIComponent(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"200\" height=\"180\" viewBox=\"0 0 200 180\">\r\n    <defs>\r\n      <linearGradient id=\"path1\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\r\n        <stop offset=\"0%\" style=\"stop-color:#e8c878\"/>\r\n        <stop offset=\"100%\" style=\"stop-color:#c8a850\"/>\r\n      </linearGradient>\r\n    </defs>\r\n    <rect width=\"200\" height=\"180\" fill=\"#d4e8b8\"/>\r\n    <rect x=\"0\" y=\"100\" width=\"200\" height=\"80\" fill=\"#c8b870\"/>\r\n    <path d=\"M70,180 Q100,90 130,180\" fill=\"#d4c880\" opacity=\"0.8\"/>\r\n    <ellipse cx=\"40\" cy=\"80\" rx=\"30\" ry=\"25\" fill=\"#4a8a3c\" opacity=\"0.8\"/>\r\n    <ellipse cx=\"160\" cy=\"75\" rx=\"25\" ry=\"22\" fill=\"#5a9a4c\" opacity=\"0.7\"/>\r\n    <rect x=\"35\" y=\"103\" width=\"8\" height=\"45\" fill=\"#7b5230\"/>\r\n    <rect x=\"155\" y=\"95\" width=\"6\" height=\"38\" fill=\"#7b5230\"/>\r\n    <ellipse cx=\"80\" cy=\"140\" rx=\"30\" ry=\"15\" fill=\"#d4a830\" opacity=\"0.6\"/>\r\n    <ellipse cx=\"120\" cy=\"148\" rx=\"22\" ry=\"12\" fill=\"#c49820\" opacity=\"0.7\"/>\r\n    <circle cx=\"85\" cy=\"138\" r=\"6\" fill=\"#f8d840\"/>\r\n    <circle cx=\"115\" cy=\"145\" r=\"5\" fill=\"#f8c830\"/>\r\n    <circle cx=\"100\" cy=\"135\" r=\"4\" fill=\"#e8d850\"/>\r\n    <path d=\"M50,115 Q100,100 150,112\" fill=\"none\" stroke=\"#b89040\" stroke-width=\"2\" opacity=\"0.6\"/>\r\n  </svg>`)}`,\r\n];\r\n\r\ntype Tab = \"all\" | \"friends\" | \"groups\";\r\n\r\nfunction ArtworkGallery() {\r\n    return (\r\n        <div className=\"relative w-56 h-52 my-1\">\r\n            {artworkImages.map((src, i) => (\r\n                <motion.div\r\n                    key={i}\r\n                    initial={{ opacity: 0, scale: 0.8, rotate: [-8, 3, -4][i] }}\r\n                    animate={{ opacity: 1, scale: 1, rotate: [-8, 3, -4][i] }}\r\n                    transition={{ duration: 0.4, delay: i * 0.1 }}\r\n                    style={{\r\n                        position: \"absolute\",\r\n                        top: `${[0, 20, 45][i]}px`,\r\n                        left: `${[10, 30, 5][i]}px`,\r\n                        zIndex: i + 1,\r\n                    }}\r\n                    whileHover={{ scale: 1.05, zIndex: 10, transition: { duration: 0.2 } }}\r\n                    className=\"w-36 h-28 rounded-xl overflow-hidden shadow-lg border-2 border-white cursor-pointer\"\r\n                >\r\n                    <img src={src} alt={`Artwork ${i + 1}`} className=\"w-full h-full object-cover\" />\r\n                </motion.div>\r\n            ))}\r\n        </div>\r\n    );\r\n}\r\n\r\nfunction Sidebar({ selectedContact, onSelectContact, isMobileOpen, onMobileClose }: {\r\n    selectedContact: ContactData | null;\r\n    onSelectContact: (contact: ContactData) => void;\r\n    isMobileOpen: boolean;\r\n    onMobileClose: () => void;\r\n}) {\r\n    const [activeTab, setActiveTab] = useState<Tab>(\"all\");\r\n    const [search, setSearch] = useState(\"\");\r\n\r\n    const tabs: { label: string; key: Tab; count: number }[] = [\r\n        { label: \"All\", key: \"all\", count: contacts.length },\r\n        { label: \"Friends\", key: \"friends\", count: contacts.filter(c => c.tab === \"friends\").length },\r\n        { label: \"Groups\", key: \"groups\", count: contacts.filter(c => c.tab === \"groups\").length },\r\n    ];\r\n\r\n    const filtered = contacts.filter(c => {\r\n        const matchTab = activeTab === \"all\" || c.tab === activeTab;\r\n        const matchSearch = c.name.toLowerCase().includes(search.toLowerCase());\r\n        return matchTab && matchSearch;\r\n    });\r\n\r\n    return (\r\n        <>\r\n            {/* Mobile overlay */}\r\n            <AnimatePresence>\r\n                {isMobileOpen && (\r\n                    <motion.div\r\n                        initial={{ opacity: 0 }}\r\n                        animate={{ opacity: 1 }}\r\n                        exit={{ opacity: 0 }}\r\n                        className=\"fixed inset-0 bg-black/30 z-20 md:hidden\"\r\n                        onClick={onMobileClose}\r\n                    />\r\n                )}\r\n            </AnimatePresence>\r\n\r\n            <motion.aside\r\n                initial={false}\r\n                animate={{ x: isMobileOpen ? 0 : undefined }}\r\n                className={`\r\n                  fixed md:relative z-30 md:z-auto\r\n                  w-[320px] md:w-[320px] lg:w-[340px]\r\n                  h-full flex flex-col\r\n                  bg-white border-r border-gray-100\r\n                  transition-transform duration-300\r\n                  ${isMobileOpen ? \"translate-x-0\" : \"-translate-x-full md:translate-x-0\"}\r\n                `}\r\n            >\r\n                {/* Header */}\r\n                <div className=\"p-4 flex items-center justify-between\">\r\n                    <div className=\"w-10 h-10 rounded-md overflow-hidden\">\r\n                        <img\r\n                            src=\"https://bagui.vercel.app/logoR.png\"\r\n                            alt=\"Me\"\r\n                            className=\"w-full h-full object-cover\"\r\n                        />\r\n                    </div>\r\n                    <div className=\"flex items-center gap-1\">\r\n                        <button className=\"w-9 h-9 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 cursor-pointer\">\r\n                            <Bell size={18} />\r\n                        </button>\r\n                        <button className=\"w-9 h-9 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 cursor-pointer\">\r\n                            <MoreVertical size={18} />\r\n                        </button>\r\n                    </div>\r\n                </div>\r\n\r\n                {/* Search */}\r\n                <div className=\"px-4 pb-3\">\r\n                    <div className=\"relative\">\r\n                        <Search size={15} className=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 cursor-pointer\" />\r\n                        <input\r\n                            value={search}\r\n                            onChange={e => setSearch(e.target.value)}\r\n                            placeholder=\"Search chats\"\r\n                            className=\"w-full pl-9 pr-4 py-2 bg-gray-100 rounded-xl text-sm text-gray-700 placeholder:text-gray-400 outline-none focus:ring-2 focus:ring-blue-200 transition-all\"\r\n                        />\r\n                    </div>\r\n                </div>\r\n\r\n                {/* Tabs */}\r\n                <div className=\"px-4 pb-3 flex items-center gap-1\">\r\n                    {tabs.map(tab => (\r\n                        <button\r\n                            key={tab.key}\r\n                            onClick={() => setActiveTab(tab.key)}\r\n                            className={`relative flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-medium transition-colors cursor-pointer ${\r\n                                activeTab === tab.key\r\n                                    ? \"text-gray-900\"\r\n                                    : \"text-gray-500 hover:text-gray-700\"\r\n                            }`}\r\n                        >\r\n                            {activeTab === tab.key && (\r\n                                <motion.span\r\n                                    layoutId=\"tab-bg\"\r\n                                    className=\"absolute inset-0 bg-gray-100 rounded-full\"\r\n                                />\r\n                            )}\r\n                            <span className=\"relative\">{tab.label}</span>\r\n                            <span className={`relative text-xs px-1.5 py-0.5 rounded-full font-semibold ${\r\n                                activeTab === tab.key ? \"bg-gray-800 text-white\" : \"bg-gray-200 text-gray-600\"\r\n                            }`}>\r\n                                {tab.count}\r\n                              </span>\r\n                        </button>\r\n                    ))}\r\n                </div>\r\n\r\n                {/* Contact list */}\r\n                <div className=\"flex-1 overflow-y-auto \">\r\n                    <AnimatePresence mode=\"popLayout\">\r\n                        {filtered.map((contact, i) => (\r\n                            <motion.button\r\n                                key={contact.id}\r\n                                initial={{ opacity: 0, y: 8 }}\r\n                                animate={{ opacity: 1, y: 0 }}\r\n                                exit={{ opacity: 0, x: -20 }}\r\n                                transition={{ duration: 0.18, delay: i * 0.03 }}\r\n                                onClick={() => { onSelectContact(contact); onMobileClose(); }}\r\n                                className={`w-full flex items-center gap-3 px-4 py-3 transition-colors text-left cursor-pointer ${\r\n                                    selectedContact?.id === contact.id\r\n                                        ? \"bg-gray-100\"\r\n                                        : \"hover:bg-gray-50\"\r\n                                }`}\r\n                            >\r\n                                {/* Avatar */}\r\n                                <div className=\"relative flex-shrink-0\">\r\n                                    {avatars[contact.avatar] ? (\r\n                                        <img\r\n                                            src={avatars[contact.avatar]}\r\n                                            alt={contact.name}\r\n                                            className=\"w-12 h-12 rounded-full object-cover\"\r\n                                        />\r\n                                    ) : (\r\n                                        <div className=\"w-12 h-12 rounded-full bg-gray-400 flex items-center justify-center text-white font-semibold text-sm\">\r\n                                            {contact.avatar}\r\n                                        </div>\r\n                                    )}\r\n\r\n                                    {contact.online && (\r\n                                        <span className=\"absolute bottom-0 right-0 w-3 h-3 bg-green-500 border-2 border-white rounded-full\" />\r\n                                    )}\r\n                                </div>\r\n\r\n                                {/* Info */}\r\n                                <div className=\"flex-1 min-w-0\">\r\n                                    <div className=\"flex items-center justify-between mb-0.5\">\r\n                                        <div className=\"flex items-center gap-1 min-w-0\">\r\n                                            <span className=\"font-semibold text-gray-900 text-sm truncate\">{contact.name}</span>\r\n                                            {contact.verified && (\r\n                                                <span className=\"w-4 h-4 rounded-full bg-blue-500 flex items-center justify-center flex-shrink-0\">\r\n                                                  <CheckCheck size={9} className=\"text-white\" />\r\n                                                </span>\r\n                                            )}\r\n                                        </div>\r\n                                        <span className=\"text-xs text-gray-400 flex-shrink-0 ml-2\">{contact.time}</span>\r\n                                    </div>\r\n                                    <div className=\"flex items-center justify-between\">\r\n                                        <p className=\"text-sm text-gray-500 truncate\">{contact.lastMessage}</p>\r\n                                        {contact.unread && (\r\n                                            <span className=\"ml-2 min-w-5 h-5 px-1 rounded-full bg-gray-900 text-white text-xs font-semibold flex items-center justify-center flex-shrink-0\">\r\n                                                {contact.unread}\r\n                                            </span>\r\n                                        )}\r\n                                    </div>\r\n                                </div>\r\n                            </motion.button>\r\n                        ))}\r\n                    </AnimatePresence>\r\n                </div>\r\n\r\n                {/* New chat button */}\r\n                <div className=\"p-4\">\r\n                    <motion.button\r\n                        whileHover={{ scale: 1.02 }}\r\n                        whileTap={{ scale: 0.98 }}\r\n                        className=\"w-full flex items-center justify-center gap-2 py-3.5 bg-black text-white rounded-2xl font-medium text-sm transition-colors cursor-pointer\"\r\n                    >\r\n                        <Edit3 size={16} />\r\n                        Start a new chat\r\n                    </motion.button>\r\n                </div>\r\n            </motion.aside>\r\n        </>\r\n    );\r\n}\r\n\r\nfunction ChatWindow({ contact, onBack }: { contact: ContactData | null; onBack: () => void }) {\r\n    const [messages, setMessages] = useState<Message[]>(contact?.messages || []);\r\n    const [input, setInput] = useState(\"\");\r\n    const [isTyping, setIsTyping] = useState(false);\r\n    const bottomRef = useRef<HTMLDivElement>(null);\r\n\r\n    useEffect(() => {\r\n        setMessages(contact?.messages || []);\r\n    }, [contact]);\r\n\r\n    useEffect(() => {\r\n        bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\r\n    }, [messages]);\r\n\r\n    const sendMessage = () => {\r\n        if (!input.trim()) return;\r\n        const newMsg: Message = {\r\n            id: Date.now().toString(),\r\n            content: input,\r\n            sender: \"me\",\r\n            timestamp: new Date().toLocaleTimeString(\"fr\", { hour: \"2-digit\", minute: \"2-digit\" }),\r\n            type: \"text\",\r\n        };\r\n        setMessages(prev => [...prev, newMsg]);\r\n        setInput(\"\");\r\n\r\n        // Simulate reply\r\n        setIsTyping(true);\r\n        setTimeout(() => {\r\n            setIsTyping(false);\r\n            const replies = [\r\n                \"Great! 😊\",\r\n                \"I see, interesting!\",\r\n                \"Thanks for the info!\",\r\n                \"Alright, we’ll talk soon.\",\r\n                \"👍\"\r\n            ];\r\n            setMessages(prev => [...prev, {\r\n                id: Date.now().toString(),\r\n                content: replies[Math.floor(Math.random() * replies.length)],\r\n                sender: \"other\",\r\n                timestamp: new Date().toLocaleTimeString(\"fr\", { hour: \"2-digit\", minute: \"2-digit\" }),\r\n                type: \"text\",\r\n            }]);\r\n        }, 1500);\r\n    };\r\n\r\n    if (!contact) {\r\n        return (\r\n            <div className=\"flex-1 hidden md:flex items-center justify-center bg-gray-50\">\r\n                <motion.div\r\n                    initial={{ opacity: 0, y: 20 }}\r\n                    animate={{ opacity: 1, y: 0 }}\r\n                    className=\"text-center\"\r\n                >\r\n                    <div className=\"w-20 h-20 rounded-full bg-gray-200 flex items-center justify-center mx-auto mb-4\">\r\n                        <ImageIcon size={32} className=\"text-gray-400\" />\r\n                    </div>\r\n                    <p className=\"text-gray-500 font-medium\">Select a conversation</p>\r\n                    <p className=\"text-gray-400 text-sm mt-1\">Choose a contact to get started</p>\r\n                </motion.div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    return (\r\n        <div className=\"flex-1 flex flex-col bg-gray-50 min-w-0\">\r\n            {/* Header */}\r\n            <motion.div\r\n                initial={{ y: -20, opacity: 0 }}\r\n                animate={{ y: 0, opacity: 1 }}\r\n                className=\"flex items-center gap-3 px-4 py-3 bg-white border-b border-gray-100 flex-shrink-0\"\r\n            >\r\n                <button\r\n                    onClick={onBack}\r\n                    className=\"md:hidden w-9 h-9 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-600\"\r\n                >\r\n                    <ChevronLeft size={20} />\r\n                </button>\r\n\r\n                <div className=\"relative flex-shrink-0\">\r\n                    {avatars[contact.avatar] ? (\r\n                        <img\r\n                            src={avatars[contact.avatar]}\r\n                            alt={contact.name}\r\n                            className=\"w-10 h-10 rounded-full object-cover\"\r\n                        />\r\n                    ) : (\r\n                        <div className=\"w-10 h-10 rounded-full bg-gray-400 flex items-center justify-center text-white font-semibold text-xs\">\r\n                            {contact.avatar}\r\n                        </div>\r\n                    )}\r\n\r\n                    {contact.online && (\r\n                        <span className=\"absolute bottom-0 right-0 w-2.5 h-2.5 bg-green-500 border-2 border-white rounded-full\" />\r\n                    )}\r\n                </div>\r\n\r\n                <div className=\"flex-1 min-w-0\">\r\n                    <p className=\"font-semibold text-gray-900 text-sm leading-tight\">{contact.name}</p>\r\n                    <p className=\"text-xs text-gray-400 truncate\">\r\n                        {contact.online ? \"Online\" : contact.lastSeen ? `Seen ${contact.lastSeen}` : \"Offline\"}\r\n                    </p>\r\n                </div>\r\n\r\n                <div className=\"flex items-center gap-1 flex-shrink-0\">\r\n                    <button className=\"w-9 h-9 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 cursor-pointer\">\r\n                        <Search size={17} />\r\n                    </button>\r\n                    <button className=\"w-9 h-9 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 cursor-pointer\">\r\n                        <MoreVertical size={17} />\r\n                    </button>\r\n                </div>\r\n            </motion.div>\r\n\r\n            {/* Messages */}\r\n            <div className=\"flex-1 overflow-y-auto px-4 py-4 space-y-1\">\r\n                <AnimatePresence initial={false}>\r\n                    {messages.map((msg, i) => {\r\n                        const isSent = msg.sender === \"me\";\r\n                        const isFirst = i === 0 || messages[i - 1].sender !== msg.sender;\r\n\r\n                        return (\r\n                            <motion.div\r\n                                key={msg.id}\r\n                                initial={{ opacity: 0, y: 16, scale: 0.95 }}\r\n                                animate={{ opacity: 1, y: 0, scale: 1 }}\r\n                                transition={{ duration: 0.25, ease: \"easeOut\" }}\r\n                                className={`flex flex-col ${isSent ? \"items-end\" : \"items-start\"} ${isFirst ? \"mt-4\" : \"mt-1\"}`}\r\n                            >\r\n                                {msg.type === \"images\" ? (\r\n                                    <ArtworkGallery />\r\n                                ) : (\r\n                                    <div\r\n                                        className={`max-w-[75%] md:max-w-[60%] px-4 py-2.5 rounded-2xl text-sm leading-relaxed ${\r\n                                            isSent\r\n                                                ? \"bg-black/90 text-white rounded-br-sm\"\r\n                                                : \"bg-white text-gray-800 shadow-sm rounded-bl-sm\"\r\n                                        }`}\r\n                                    >\r\n                                        <p>{msg.content}</p>\r\n                                        <p className={`text-[10px] mt-1 ${isSent ? \"text-blue-100\" : \"text-gray-400\"} text-right`}>\r\n                                            {msg.timestamp}\r\n                                        </p>\r\n                                    </div>\r\n                                )}\r\n                            </motion.div>\r\n                        );\r\n                    })}\r\n                </AnimatePresence>\r\n\r\n                {/* Typing indicator */}\r\n                <AnimatePresence>\r\n                    {isTyping && (\r\n                        <motion.div\r\n                            initial={{ opacity: 0, y: 10 }}\r\n                            animate={{ opacity: 1, y: 0 }}\r\n                            exit={{ opacity: 0, y: 10 }}\r\n                            className=\"flex items-end gap-2 mt-2\"\r\n                        >\r\n                            <div className=\"bg-white shadow-sm rounded-2xl rounded-bl-sm px-4 py-3 flex items-center gap-1\">\r\n                                {[0, 1, 2].map(i => (\r\n                                    <motion.span\r\n                                        key={i}\r\n                                        animate={{ y: [0, -4, 0] }}\r\n                                        transition={{ duration: 0.6, repeat: Infinity, delay: i * 0.15 }}\r\n                                        className=\"w-2 h-2 rounded-full bg-gray-400 block\"\r\n                                    />\r\n                                ))}\r\n                            </div>\r\n                        </motion.div>\r\n                    )}\r\n                </AnimatePresence>\r\n\r\n                <div ref={bottomRef} />\r\n            </div>\r\n\r\n            {/* Input */}\r\n            <div className=\"px-4 py-3 bg-white border-t border-gray-100 flex-shrink-0\">\r\n                <div className=\"flex items-center gap-2\">\r\n                    <motion.button\r\n                        whileHover={{ scale: 1.1 }}\r\n                        whileTap={{ scale: 0.9 }}\r\n                        className=\"w-9 h-9 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-colors text-gray-500 flex-shrink-0 cursor-pointer\"\r\n                    >\r\n                        <Plus size={18} />\r\n                    </motion.button>\r\n\r\n                    <div className=\"flex-1 relative\">\r\n                        <input\r\n                            value={input}\r\n                            onChange={e => setInput(e.target.value)}\r\n                            onKeyDown={e => e.key === \"Enter\" && sendMessage()}\r\n                            placeholder=\"Type a message\"\r\n                            className=\"w-full px-4 py-2.5 bg-gray-100 rounded-xl text-sm text-gray-800 placeholder:text-gray-400 outline-none focus:ring-2 focus:ring-gray-200 transition-all pr-10\"\r\n                        />\r\n                        <button className=\"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors\">\r\n                            <Smile size={17} />\r\n                        </button>\r\n                    </div>\r\n\r\n                    <motion.button\r\n                        whileHover={{ scale: 1.05 }}\r\n                        whileTap={{ scale: 0.95 }}\r\n                        onClick={sendMessage}\r\n                        className={`w-9 h-9 flex items-center justify-center rounded-full flex-shrink-0 transition-colors cursor-pointer ${\r\n                            input.trim()\r\n                                ? \"bg-black hover:bg-[#000]/80 text-white\"\r\n                                : \"bg-gray-100 text-gray-400\"\r\n                        }`}\r\n                    >\r\n                        <Send size={16} className={input.trim() ? \"\" : \"opacity-50\"} />\r\n                    </motion.button>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n\r\nexport default function ChatApp() {\r\n    const [selectedContact, setSelectedContact] = useState<ContactData | null>(null);\r\n    const [isMobileOpen, setIsMobileOpen] = useState(false);\r\n\r\n    return (\r\n        <div className=\"flex h-screen bg-white\">\r\n            <Sidebar\r\n                selectedContact={selectedContact}\r\n                onSelectContact={setSelectedContact}\r\n                isMobileOpen={isMobileOpen}\r\n                onMobileClose={() => setIsMobileOpen(false)}\r\n            />\r\n            {selectedContact ? (\r\n                <ChatWindow contact={selectedContact} onBack={() => setSelectedContact(null)} />\r\n            ) : (\r\n                <ChatWindow contact={null} onBack={() => {}} />\r\n            )}\r\n        </div>\r\n    );\r\n}\r\n",
      "type": "registry:block",
      "target": "components/Dashboard/Chatapp1.tsx"
    }
  ],
  "type": "registry:block"
}