import { motion } from "framer-motion"; import { Link } from "wouter"; import { ArrowLeft, Send, Mail, MailOpen, User, Clock, Loader2 } from "lucide-react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import gridBg from '@assets/generated_images/dark_subtle_digital_grid_texture.png'; interface Message { id: string; sender_id: string; sender_name: string; content: string; timestamp: string; read: boolean; avatar?: string | null; } export default function Messages() { const queryClient = useQueryClient(); const [selectedMessage, setSelectedMessage] = useState(null); const [replyText, setReplyText] = useState(""); const { data: messages, isLoading } = useQuery({ queryKey: ["/api/messages"], }); const markReadMutation = useMutation({ mutationFn: async (messageId: string) => { const response = await fetch(`/api/messages/${messageId}/read`, { method: "PUT", }); if (!response.ok) throw new Error("Failed to mark as read"); return response.json(); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["/api/messages"] }); }, }); const sendMessageMutation = useMutation({ mutationFn: async ({ recipient_id, content }: { recipient_id: string; content: string }) => { const response = await fetch("/api/messages", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ recipient_id, content }), }); if (!response.ok) throw new Error("Failed to send message"); return response.json(); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["/api/messages"] }); setReplyText(""); setSelectedMessage(null); }, }); const handleMessageClick = (message: Message) => { setSelectedMessage(message); if (!message.read) { markReadMutation.mutate(message.id); } }; const handleSendReply = () => { if (!selectedMessage || !replyText.trim()) return; sendMessageMutation.mutate({ recipient_id: selectedMessage.sender_id, content: replyText, }); }; const formatTime = (timestamp: string) => { const date = new Date(timestamp); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffHours = diffMs / (1000 * 60 * 60); if (diffHours < 1) { const diffMins = Math.floor(diffMs / (1000 * 60)); return `${diffMins}m ago`; } else if (diffHours < 24) { return `${Math.floor(diffHours)}h ago`; } else { const diffDays = Math.floor(diffHours / 24); return `${diffDays}d ago`; } }; const unreadCount = messages?.filter((m) => !m.read).length || 0; return (
{/* Background */}
{/* Header */}

Messages

{unreadCount > 0 ? `${unreadCount} unread message${unreadCount > 1 ? "s" : ""}` : "No unread messages"}

{isLoading ? (
) : (
{/* Messages List */}

Inbox

{messages && messages.length > 0 ? ( messages.map((message) => ( handleMessageClick(message)} className={`w-full text-left p-4 border-b border-border hover:bg-secondary/50 transition-colors ${ selectedMessage?.id === message.id ? "bg-secondary/70" : message.read ? "opacity-70" : "bg-secondary/30" }`} whileHover={{ x: 4 }} >
{message.avatar ? ( {message.sender_name} ) : (
)}
{message.sender_name} {formatTime(message.timestamp)}

{message.content}

{!message.read && (
)}
)) ) : (

No messages yet

)}
{/* Message Detail */}
{selectedMessage ? ( {/* Message Header */}
{selectedMessage.avatar ? ( {selectedMessage.sender_name} ) : (
)}

{selectedMessage.sender_name}

{new Date(selectedMessage.timestamp).toLocaleString()}

{/* Message Content */}

{selectedMessage.content}

{/* Reply Section */}