Add a member search bar
This commit is contained in:
parent
f5112cea92
commit
48dc0afe1a
@ -41,6 +41,7 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
const [newMessage, setNewMessage] = useState("")
|
const [newMessage, setNewMessage] = useState("")
|
||||||
const [pairingProcesses, setPairingProcesses] = useState<PairingProcess[]>([])
|
const [pairingProcesses, setPairingProcesses] = useState<PairingProcess[]>([])
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
const [searchQuery, setSearchQuery] = useState("")
|
||||||
|
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const userId = searchParams.get("user")
|
const userId = searchParams.get("user")
|
||||||
@ -122,9 +123,9 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
avatar: avatar,
|
avatar: avatar,
|
||||||
lastMessage: "",
|
lastMessage: "",
|
||||||
lastMessageTime: "",
|
lastMessageTime: "",
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
isOnline: true,
|
isOnline: true,
|
||||||
isTyping: false,
|
isTyping: false,
|
||||||
pairingId: process.id
|
pairingId: process.id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -132,6 +133,18 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
|
|
||||||
const messages: any[] = []
|
const messages: any[] = []
|
||||||
|
|
||||||
|
// Filter conversations based on search query
|
||||||
|
const filteredConversations = conversations.filter(conversation => {
|
||||||
|
if (!searchQuery.trim()) return true
|
||||||
|
|
||||||
|
// Search by ID (process ID)
|
||||||
|
const matchesId = conversation.id.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
|
// Search by name
|
||||||
|
const matchesName = conversation.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
|
|
||||||
|
return matchesId || matchesName
|
||||||
|
})
|
||||||
|
|
||||||
const currentConversation = conversations.find((conv) => conv.id === selectedConversation)
|
const currentConversation = conversations.find((conv) => conv.id === selectedConversation)
|
||||||
|
|
||||||
const handleSendMessage = () => {
|
const handleSendMessage = () => {
|
||||||
@ -141,104 +154,25 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStatusIcon = (status: string) => {
|
|
||||||
switch (status) {
|
|
||||||
case "sent":
|
|
||||||
return <Clock className="h-3 w-3 text-gray-400" />
|
|
||||||
case "delivered":
|
|
||||||
return <CheckCheck className="h-3 w-3 text-gray-400" />
|
|
||||||
case "read":
|
|
||||||
return <CheckCheck className="h-3 w-3 text-blue-500" />
|
|
||||||
default:
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAnalysisIcon = (analysisType: string) => {
|
|
||||||
switch (analysisType) {
|
|
||||||
case "document":
|
|
||||||
return <FileText className="h-4 w-4" />
|
|
||||||
case "comparative":
|
|
||||||
return <BarChart3 className="h-4 w-4" />
|
|
||||||
case "security":
|
|
||||||
return <Shield className="h-4 w-4" />
|
|
||||||
case "performance":
|
|
||||||
return <TrendingUp className="h-4 w-4" />
|
|
||||||
default:
|
|
||||||
return <Brain className="h-4 w-4" />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderAIMessage = (message: any) => {
|
|
||||||
return (
|
|
||||||
<div className="flex justify-start">
|
|
||||||
<div className="max-w-4xl">
|
|
||||||
<div className="flex items-center space-x-2 mb-2">
|
|
||||||
<div className="w-8 h-8 bg-gradient-to-r from-purple-500 to-blue-500 rounded-full flex items-center justify-center">
|
|
||||||
<Brain className="h-4 w-4 text-white" />
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">IA DocV</span>
|
|
||||||
<Badge className="bg-gradient-to-r from-purple-100 to-blue-100 dark:from-purple-800 dark:to-blue-800 text-purple-700 dark:text-purple-200 border-purple-200 dark:border-purple-700 text-xs">
|
|
||||||
{getAnalysisIcon(message.analysisType)}
|
|
||||||
<span className="ml-1">
|
|
||||||
{message.analysisType === "document"
|
|
||||||
? "Analyse Document"
|
|
||||||
: message.analysisType === "comparative"
|
|
||||||
? "Analyse Comparative"
|
|
||||||
: "Analyse IA"}
|
|
||||||
</span>
|
|
||||||
</Badge>
|
|
||||||
{message.confidence && (
|
|
||||||
<Badge className="bg-green-100 dark:bg-green-800 text-green-700 dark:text-green-200 border-green-200 dark:border-green-700 text-xs">
|
|
||||||
<CheckCircle className="h-3 w-3 mr-1" />
|
|
||||||
{message.confidence}% fiable
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-gradient-to-r from-purple-50 to-blue-50 dark:from-purple-900 dark:to-blue-900 border border-purple-200 dark:border-purple-700 rounded-lg p-4 shadow-sm">
|
|
||||||
<div className="prose prose-sm max-w-none">
|
|
||||||
<div className="whitespace-pre-line text-gray-800 dark:text-gray-100 leading-relaxed">{message.content}</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between mt-4 pt-3 border-t border-purple-200 dark:border-purple-700">
|
|
||||||
<div className="flex items-center space-x-4 text-xs text-gray-600 dark:text-gray-400">
|
|
||||||
<div className="flex items-center space-x-1">
|
|
||||||
<Zap className="h-3 w-3" />
|
|
||||||
<span>Traité en {message.processingTime}</span>
|
|
||||||
</div>
|
|
||||||
{message.documentName && (
|
|
||||||
<div className="flex items-center space-x-1">
|
|
||||||
<FileText className="h-3 w-3" />
|
|
||||||
<span>{message.documentName}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<span className="text-xs text-purple-600 dark:text-purple-400">{message.timestamp}</span>
|
|
||||||
<div>{getStatusIcon(message.status)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${heightClass} flex`}>
|
<div className={`${heightClass} flex`}>
|
||||||
<div className="w-80 border-r bg-white dark:bg-gray-800 flex flex-col">
|
<div className="w-80 border-r bg-white dark:bg-gray-800 flex flex-col">
|
||||||
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
|
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="mb-4">
|
||||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">Messages</h2>
|
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-3">Messages</h2>
|
||||||
<Button size="sm">
|
<div className="relative">
|
||||||
<Plus className="h-4 w-4" />
|
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||||
</Button>
|
<Input
|
||||||
|
placeholder="Rechercher par ID ou nom..."
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
className="pl-10 bg-gray-50 dark:bg-gray-700 border-gray-200 dark:border-gray-600"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 overflow-y-auto">
|
<div className="flex-1 overflow-y-auto">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="flex items-center justify-center p-8">
|
<div className="flex items-center justify-center p-8">
|
||||||
<div className="text-gray-500 dark:text-gray-400">Chargement des processus de pairing...</div>
|
<div className="text-gray-500 dark:text-gray-400">Chargement des processus de pairing...</div>
|
||||||
@ -250,14 +184,14 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
onClick={() => setSelectedConversation(conversation.id)}
|
onClick={() => setSelectedConversation(conversation.id)}
|
||||||
className={`p-4 border-b cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 ${
|
className={`p-4 border-b cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 ${
|
||||||
selectedConversation === conversation.id
|
selectedConversation === conversation.id
|
||||||
? "bg-blue-50 dark:bg-blue-900 border-r-2 border-blue-500 dark:border-blue-400"
|
? "bg-blue-50 dark:bg-blue-900 border-r-2 border-blue-500 dark:border-blue-400"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-start space-x-3">
|
<div className="flex items-start space-x-3">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-800 rounded-full flex items-center justify-center">
|
<div className="w-12 h-12 bg-blue-100 dark:bg-blue-800 rounded-full flex items-center justify-center">
|
||||||
<span className="text-blue-600 dark:text-blue-400 font-medium">{conversation.avatar}</span>
|
<span className="text-blue-600 dark:text-blue-400 font-medium">{conversation.avatar}</span>
|
||||||
</div>
|
</div>
|
||||||
{conversation.isOnline && (
|
{conversation.isOnline && (
|
||||||
<Circle className="absolute -bottom-1 -right-1 h-4 w-4 text-green-500 fill-current" />
|
<Circle className="absolute -bottom-1 -right-1 h-4 w-4 text-green-500 fill-current" />
|
||||||
@ -275,48 +209,59 @@ export default function Chat({ heightClass = "h-[calc(100vh-8rem)]", processes,
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))
|
||||||
</div>
|
) : (
|
||||||
|
<div className="flex items-center justify-center p-8">
|
||||||
|
<div className="text-center">
|
||||||
|
<Search className="h-8 w-8 mx-auto text-gray-400 dark:text-gray-500 mb-2" />
|
||||||
|
<p className="text-gray-500 dark:text-gray-400">Aucun membre trouvé</p>
|
||||||
|
<p className="text-xs text-gray-400 dark:text-gray-500 mt-1">
|
||||||
|
Essayez de rechercher par ID ou nom
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
{currentConversation ? (
|
{currentConversation ? (
|
||||||
<>
|
<>
|
||||||
<div className="p-4 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
|
<div className="p-4 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="w-10 h-10 bg-blue-100 dark:bg-blue-800 rounded-full flex items-center justify-center">
|
<div className="w-10 h-10 bg-blue-100 dark:bg-blue-800 rounded-full flex items-center justify-center">
|
||||||
<span className="text-blue-600 dark:text-blue-400 font-medium">{currentConversation.avatar}</span>
|
<span className="text-blue-600 dark:text-blue-400 font-medium">{currentConversation.avatar}</span>
|
||||||
</div>
|
</div>
|
||||||
{currentConversation.isOnline && (
|
{currentConversation.isOnline && (
|
||||||
<Circle className="absolute -bottom-1 -right-1 h-3 w-3 text-green-500 fill-current" />
|
<Circle className="absolute -bottom-1 -right-1 h-3 w-3 text-green-500 fill-current" />
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="font-medium text-gray-900 dark:text-gray-100">{currentConversation.name}</h3>
|
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
||||||
{currentConversation.isOnline ? "En ligne" : "Hors ligne"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-2">
|
<div>
|
||||||
<Button variant="outline" size="sm">
|
<h3 className="font-medium text-gray-900 dark:text-gray-100">{currentConversation.name}</h3>
|
||||||
<MoreHorizontal className="h-4 w-4 text-gray-900 dark:text-gray-100" />
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
</Button>
|
{currentConversation.isOnline ? "En ligne" : "Hors ligne"}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Button variant="outline" size="sm">
|
||||||
|
<MoreHorizontal className="h-4 w-4 text-gray-900 dark:text-gray-100" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900">
|
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900">
|
||||||
<div className="flex items-center justify-center h-full">
|
<div className="flex items-center justify-center h-full">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<MessageSquare className="h-12 w-12 mx-auto text-gray-400 dark:text-gray-500 mb-4" />
|
<MessageSquare className="h-12 w-12 mx-auto text-gray-400 dark:text-gray-500 mb-4" />
|
||||||
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">Aucun message</h3>
|
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">Aucun message</h3>
|
||||||
<p className="text-gray-600 dark:text-gray-400">Commencez une conversation en envoyant un message</p>
|
<p className="text-gray-600 dark:text-gray-400">Commencez une conversation en envoyant un message</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="p-4 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
|
<div className="p-4 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
|
||||||
<div className="flex items-end space-x-2">
|
<div className="flex items-end space-x-2">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user