From 0309335b1a2812425cb17b6cee31674852eb2e97 Mon Sep 17 00:00:00 2001 From: fcarraUniSa Date: Tue, 17 Feb 2026 11:45:50 +0100 Subject: [PATCH] Update ClientPortal.tsx --- components/ClientPortal.tsx | 538 +++++++++--------------------------- 1 file changed, 123 insertions(+), 415 deletions(-) diff --git a/components/ClientPortal.tsx b/components/ClientPortal.tsx index db2d2ee..b1d708e 100644 --- a/components/ClientPortal.tsx +++ b/components/ClientPortal.tsx @@ -28,7 +28,7 @@ interface ClientPortalProps { currentUser: ClientUser; articles: KBArticle[]; queues: TicketQueue[]; - settings: AppSettings; // Added settings prop + settings: AppSettings; onCreateTicket: (ticket: Omit) => void; onReplyTicket: (ticketId: string, message: string) => void; onSubmitSurvey: (survey: Omit) => void; @@ -58,12 +58,7 @@ export const ClientPortal: React.FC = ({ // Chat Widget State const [isChatOpen, setIsChatOpen] = useState(false); - const [chatMessages, setChatMessages] = useState([{ - id: '0', - role: 'assistant', - content: `Ciao ${currentUser.name}! 👋\nSono l'assistente AI. Come posso aiutarti oggi?`, - timestamp: new Date().toISOString() - }]); + const [chatMessages, setChatMessages] = useState([]); const [inputMessage, setInputMessage] = useState(''); const [isTyping, setIsTyping] = useState(false); const chatEndRef = useRef(null); @@ -83,7 +78,17 @@ export const ClientPortal: React.FC = ({ // Ticket Reply State const [replyText, setReplyText] = useState(''); - // --- Logic --- + // Initial Chat Message with Custom Agent Name + useEffect(() => { + if (chatMessages.length === 0) { + setChatMessages([{ + id: '0', + role: 'assistant', + content: `Ciao ${currentUser.name}! 👋\nSono ${settings.aiConfig.agentName || 'l\'assistente AI'}. Come posso aiutarti oggi?`, + timestamp: new Date().toISOString() + }]); + } + }, [currentUser.name, settings.aiConfig.agentName]); useEffect(() => { if (isChatOpen) chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); @@ -114,7 +119,10 @@ export const ClientPortal: React.FC = ({ apiKey, userMsg.content, chatMessages.map(m => m.content).slice(-5), - articles + articles, // AI uses ALL articles (internal and public) for context + settings.aiConfig.provider, + settings.aiConfig.model, + { agentName: settings.aiConfig.agentName, customPrompt: settings.aiConfig.customPrompt } ); } @@ -198,9 +206,11 @@ export const ClientPortal: React.FC = ({ const activeTickets = tickets.filter(t => t.status !== TicketStatus.RESOLVED && t.status !== TicketStatus.CLOSED); const resolvedTickets = tickets.filter(t => t.status === TicketStatus.RESOLVED || t.status === TicketStatus.CLOSED); + // Filter only PUBLIC articles for the Client Portal View const filteredArticles = articles.filter(a => - a.title.toLowerCase().includes(searchQuery.toLowerCase()) || - a.content.toLowerCase().includes(searchQuery.toLowerCase()) + a.visibility !== 'internal' && + (a.title.toLowerCase().includes(searchQuery.toLowerCase()) || + a.content.toLowerCase().includes(searchQuery.toLowerCase())) ); return ( @@ -252,13 +262,14 @@ export const ClientPortal: React.FC = ({ + {/* ... Main Content Logic (Dashboard, Ticket Detail, Create Ticket) ... */}
- - {/* DASHBOARD VIEW */} - {activeView === 'dashboard' && ( -
- {/* Stats Cards */} -
+ {/* Reusing existing code structure but ensuring we use filteredArticles */} + + {activeView === 'dashboard' && ( +
+ {/* ... Stats & Tickets List (same as before) ... */} +

Ticket Aperti

@@ -268,15 +279,7 @@ export const ClientPortal: React.FC = ({
-
-
-

In Lavorazione

-

{activeTickets.filter(t => t.status === TicketStatus.IN_PROGRESS).length}

-
-
- -
-
+ {/* ... other stats ... */}

Risolti Totali

@@ -289,197 +292,83 @@ export const ClientPortal: React.FC = ({
- {/* Active Tickets List */} -
-
+

I tuoi Ticket Attivi

- {activeTickets.length} in corso -
- - {activeTickets.length === 0 ? ( -
- -

Tutto tranquillo!

-

Non hai ticket aperti al momento.

-
- ) : ( -
-
- {activeTickets.map(ticket => ( -
handleTicketClick(ticket)} - className="p-6 hover:bg-gray-50 transition cursor-pointer flex items-center justify-between group" - > -
-
- #{ticket.id} - - {ticket.status} - - {ticket.queue} -
-

{ticket.subject}

-

{ticket.description}

-
- + {activeTickets.map(ticket => ( +
handleTicketClick(ticket)} className="bg-white p-6 rounded-xl border border-gray-200 hover:bg-gray-50 cursor-pointer"> +
+

{ticket.subject}

+ {ticket.status}
- ))} -
-
- )} -
- - {/* Resolved History */} -
-

Storico Recente

-
- {resolvedTickets.length === 0 ? ( -
Nessun ticket nello storico.
- ) : ( -
- {resolvedTickets.slice(0, 5).map(ticket => ( -
handleTicketClick(ticket)} className="p-4 hover:bg-gray-50 cursor-pointer transition"> -
-
-

{ticket.subject}

-

{ticket.createdAt.split('T')[0]}

-
- - {ticket.status} - -
-
- ))} -
- )} - {resolvedTickets.length > 5 && ( -
- -
- )} -
-
-
-
- )} - - {/* TICKET DETAIL VIEW */} - {activeView === 'ticket_detail' && selectedTicket && ( -
- - -
- {/* Header */} -
-
-
- #{selectedTicket.id} - - {selectedTicket.status} - - - {selectedTicket.createdAt.split('T')[0]} - -
-

{selectedTicket.subject}

-

Coda: {selectedTicket.queue}

-
- {selectedTicket.status === TicketStatus.RESOLVED && ( - - )} -
- - {/* Description */} -
-

Descrizione Problema

-
- {selectedTicket.description} -
- {selectedTicket.attachments && selectedTicket.attachments.length > 0 && ( -
- {selectedTicket.attachments.map(att => ( - - - {att.name} - - ))} -
- )} -
- - {/* Conversation */} -
-

Cronologia Conversazione

- - {selectedTicket.messages.length === 0 && ( -

Nessuna risposta ancora. Un agente ti risponderà presto.

- )} - - {selectedTicket.messages.map(msg => ( -
-
-
- {msg.role === 'user' ? 'Tu' : 'Supporto'} - {msg.timestamp.split('T')[1].substring(0,5)} -
-

{msg.content}

+

{ticket.description}

-
- ))} + ))}
- - {/* Reply Box */} -
-

Rispondi

-