230 lines
8.1 KiB
TypeScript
230 lines
8.1 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { Badge } from "@/components/ui/badge"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Textarea } from "@/components/ui/textarea"
|
|
import {
|
|
Send,
|
|
Paperclip,
|
|
Smile,
|
|
MoreHorizontal,
|
|
Folder,
|
|
MessageSquare
|
|
} from "lucide-react"
|
|
import type { EnrichedFolderData } from "@/lib/contexts/FourNKContext";
|
|
import MessageBus from "@/lib/4nk/MessageBus"
|
|
import { iframeUrl } from "@/app/page"
|
|
|
|
// Interface pour les props (accepte null)
|
|
interface FolderChatProps {
|
|
folder: EnrichedFolderData | null;
|
|
}
|
|
|
|
// Message fictif pour la maquette
|
|
interface MockMessage {
|
|
id: number;
|
|
sender: 'me' | 'other';
|
|
name: string;
|
|
avatar: string;
|
|
text: string;
|
|
time: string;
|
|
type: 'owner' | 'general'; // Pour filtrer
|
|
}
|
|
|
|
export default function FolderChat({ folder }: FolderChatProps) {
|
|
const [newMessage, setNewMessage] = useState("")
|
|
const [activeTab, setActiveTab] = useState<'owner' | 'general'>('owner');
|
|
|
|
// Données fictives
|
|
const mockMessages: MockMessage[] = [
|
|
{ id: 1, sender: 'other', name: 'Membre A4B2 (Owner)', avatar: 'A4', text: "Validation Owner OK.", time: "14:30", type: 'owner' },
|
|
{ id: 2, sender: 'me', name: 'Vous', avatar: 'MO', text: "Parfait, merci.", time: "14:32", type: 'owner' },
|
|
{ id: 3, sender: 'other', name: 'Membre C8F1', avatar: 'C8', text: "Le client a une question sur ce dossier.", time: "14:33", type: 'general' },
|
|
{ id: 4, sender: 'me', name: 'Vous', avatar: 'MO', text: "Je regarde ça.", time: "14:34", type: 'general' },
|
|
];
|
|
|
|
// Filtre les messages basé sur l'onglet actif
|
|
const filteredMessages = mockMessages.filter(msg => msg.type === activeTab);
|
|
|
|
const handleProcessUpdate = async (processId: string, key: string, value: any) => {
|
|
try {
|
|
const messageBus = MessageBus.getInstance(iframeUrl);
|
|
await messageBus.isReady();
|
|
|
|
const updateData = {
|
|
[key]: value
|
|
};
|
|
|
|
// First update the process
|
|
const updatedProcess = await messageBus.updateProcess(processId, updateData, [], null);
|
|
if (!updatedProcess) {
|
|
throw new Error('No updated process found');
|
|
}
|
|
|
|
const newStateId = updatedProcess.diffs[0]?.state_id;
|
|
|
|
if (!newStateId) {
|
|
throw new Error('No new state id found');
|
|
}
|
|
|
|
// Then notify about the update
|
|
await messageBus.notifyProcessUpdate(processId, newStateId);
|
|
|
|
// Finally validate the state
|
|
await messageBus.validateState(processId, newStateId);
|
|
|
|
// Refresh the processes data
|
|
// const updatedProcesses = await messageBus.getProcesses();
|
|
|
|
console.log('Process updated successfully');
|
|
} catch (error) {
|
|
console.error('Error updating field:', error);
|
|
// You might want to show an error message to the user here
|
|
}
|
|
};
|
|
|
|
const handleSendMessage = () => {
|
|
if (newMessage.trim()) {
|
|
console.log(`Envoi message [${activeTab}] à:`, folder?.folderNumber, "Msg:", newMessage)
|
|
// TODO: Implémenter la logique d'envoi de message
|
|
if(!folder) return;
|
|
const key = activeTab === 'owner' ? 'messages_owner' : 'messages'
|
|
handleProcessUpdate(folder.processId, key, newMessage)
|
|
setNewMessage("")
|
|
}
|
|
}
|
|
|
|
// Si aucun dossier n'est sélectionné, afficher un placeholder
|
|
if (!folder) {
|
|
return (
|
|
<div className="flex h-full items-center justify-center bg-gray-800 text-gray-500 p-6">
|
|
<div className="text-center">
|
|
<MessageSquare className="h-12 w-12 mx-auto mb-4" />
|
|
<h3 className="text-lg font-medium text-gray-100 mb-2">
|
|
Chat de dossier
|
|
</h3>
|
|
<p className="text-gray-400">
|
|
Sélectionnez un dossier pour voir la conversation
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Si un dossier EST sélectionné, afficher le chat complet
|
|
return (
|
|
<div className="flex flex-col h-full bg-gray-800 text-gray-100">
|
|
|
|
{/* En-tête du chat */}
|
|
<div className="p-4 border-b border-gray-700">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center space-x-3">
|
|
<div className="w-10 h-10 bg-green-800 rounded-full flex items-center justify-center flex-shrink-0">
|
|
<Folder className="h-5 w-5 text-green-400" />
|
|
</div>
|
|
<div>
|
|
<h3 className="font-medium text-gray-100">
|
|
{folder.name}
|
|
</h3>
|
|
{/* ID du dossier supprimé */}
|
|
</div>
|
|
</div>
|
|
<Button variant="ghost" size="sm" className="text-gray-400 hover:text-gray-100 hover:bg-gray-700">
|
|
<MoreHorizontal className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Onglets "Owner" / "General" */}
|
|
<div className="p-2 flex border-b border-gray-700 bg-gray-900">
|
|
<Button
|
|
variant={activeTab === 'owner' ? "secondary" : "ghost"}
|
|
size="sm"
|
|
onClick={() => setActiveTab('owner')}
|
|
className={`flex-1 ${activeTab === 'owner' ? 'bg-gray-700 text-white' : 'text-gray-400 hover:text-white'}`}
|
|
>
|
|
Propriétaires
|
|
</Button>
|
|
<Button
|
|
variant={activeTab === 'general' ? "secondary" : "ghost"}
|
|
size="sm"
|
|
onClick={() => setActiveTab('general')}
|
|
className={`flex-1 ${activeTab === 'general' ? 'bg-gray-700 text-white' : 'text-gray-400 hover:text-white'}`}
|
|
>
|
|
Général
|
|
</Button>
|
|
</div>
|
|
|
|
{/* --- LISTE DES MEMBRES (SUPPRIMÉE) --- */}
|
|
|
|
{/* Zone des messages */}
|
|
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gray-900">
|
|
{filteredMessages.length > 0 ? filteredMessages.map((msg) => (
|
|
<div
|
|
key={msg.id}
|
|
className={`flex items-start gap-3 ${msg.sender === 'me' ? 'justify-end' : ''}`}
|
|
>
|
|
{msg.sender === 'other' && (
|
|
<div className="w-8 h-8 bg-blue-800 rounded-full flex items-center justify-center flex-shrink-0">
|
|
<span className="text-xs text-blue-300 font-medium">{msg.avatar}</span>
|
|
</div>
|
|
)}
|
|
<div>
|
|
<div
|
|
className={`p-3 rounded-lg ${msg.sender === 'me'
|
|
? 'bg-blue-600 text-white rounded-br-none'
|
|
: 'bg-gray-700 text-gray-100 rounded-bl-none'
|
|
}`}
|
|
>
|
|
{msg.sender === 'other' && (
|
|
<p className="text-xs font-medium text-blue-300 mb-1">{msg.name}</p>
|
|
)}
|
|
<p>{msg.text}</p>
|
|
</div>
|
|
<p className={`text-xs text-gray-500 mt-1 ${msg.sender === 'me' ? 'text-right' : ''}`}>
|
|
{msg.time}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)) : (
|
|
<div className="flex h-full items-center justify-center text-center text-gray-500 p-4">
|
|
<p>Aucun message dans le chat "{activeTab}"</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Input de message */}
|
|
<div className="p-4 border-t border-gray-700">
|
|
<div className="flex items-end space-x-2">
|
|
<Button variant="ghost" size="sm" className="text-gray-400 hover:text-gray-100 hover:bg-gray-700">
|
|
<Paperclip className="h-5 w-5" />
|
|
</Button>
|
|
<Button variant="ghost" size="sm" className="text-gray-400 hover:text-gray-100 hover:bg-gray-700">
|
|
<Smile className="h-5 w-5" />
|
|
</Button>
|
|
<Textarea
|
|
placeholder={`Message (${activeTab})...`}
|
|
value={newMessage}
|
|
onChange={(e) => setNewMessage(e.target.value)}
|
|
onKeyPress={(e) => {
|
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
e.preventDefault();
|
|
handleSendMessage();
|
|
}
|
|
}}
|
|
rows={1}
|
|
className="resize-none flex-1 bg-gray-700 border-gray-700 text-gray-100 placeholder-gray-400 focus:border-blue-500 focus:ring-0"
|
|
/>
|
|
<Button
|
|
onClick={handleSendMessage}
|
|
disabled={!newMessage.trim()}
|
|
className="bg-blue-600 hover:bg-blue-700 text-white"
|
|
>
|
|
<Send className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
} |