diff --git a/App.tsx b/App.tsx index 231cbe2..41b42fc 100644 --- a/App.tsx +++ b/App.tsx @@ -53,7 +53,8 @@ const App: React.FC = () => { queues: data.queues, articles: data.articles, surveys: data.surveys, - tickets: tickets + tickets: tickets, + settings: data.settings || prev.settings })); } catch (e) { showToast("Errore caricamento dati dal server", 'error'); @@ -63,16 +64,15 @@ const App: React.FC = () => { }; useEffect(() => { - // Carica i dati all'avvio solo se l'utente è loggato, oppure carica dati pubblici se necessario. - // In questo design, carichiamo tutto dopo il login per sicurezza, o pre-fetch. - // Per semplicità, carichiamo tutto all'avvio per popolare le liste, ma in prod si farebbe dopo auth. - // Qui chiamiamo loadData solo se c'è un utente, altrimenti auth screen - }, []); + // Carica dati al caricamento se l'utente è loggato + if (state.currentUser) { + loadData(); + } + }, [state.currentUser]); // Effect to refresh tickets periodically if logged in useEffect(() => { if (state.currentUser) { - loadData(); const interval = setInterval(loadData, 10000); // Poll every 10s return () => clearInterval(interval); } @@ -155,12 +155,10 @@ const App: React.FC = () => { body: JSON.stringify({ role, content: message }) }); - // Update local state optimistically or via re-fetch setState(prev => ({ ...prev, tickets: prev.tickets.map(t => { if (t.id !== ticketId) return t; - // Se l'utente risponde, riapri il ticket se era risolto (gestito anche dal backend) const shouldReopen = role === 'user' && t.status === TicketStatus.RESOLVED; return { ...t, @@ -254,16 +252,80 @@ const App: React.FC = () => { } }; - // --- Stub functions for settings (implement API if needed) --- - const addAgent = (agent: Agent) => { setState(prev => ({ ...prev, agents: [...prev.agents, agent] })); }; - const updateAgent = (agent: Agent) => { setState(prev => ({ ...prev, agents: prev.agents.map(a => a.id === agent.id ? agent : a) })); }; - const removeAgent = (id: string) => { setState(prev => ({ ...prev, agents: prev.agents.filter(a => a.id !== id) })); }; - const addClientUser = (user: ClientUser) => { setState(prev => ({ ...prev, clientUsers: [...prev.clientUsers, user] })); }; - const updateClientUser = (user: ClientUser) => { setState(prev => ({ ...prev, clientUsers: prev.clientUsers.map(u => u.id === user.id ? user : u) })); }; - const removeClientUser = (id: string) => { setState(prev => ({ ...prev, clientUsers: prev.clientUsers.filter(u => u.id !== id) })); }; - const updateSettings = (newSettings: AppSettings) => { setState(prev => ({ ...prev, settings: newSettings })); }; - const addQueue = (queue: TicketQueue) => { setState(prev => ({ ...prev, queues: [...prev.queues, queue] })); }; - const removeQueue = (id: string) => { setState(prev => ({ ...prev, queues: prev.queues.filter(q => q.id !== id) })); }; + // --- Settings & Management (Now with Persistence) --- + + const addAgent = async (agent: Agent) => { + try { + await apiFetch('/agents', { method: 'POST', body: JSON.stringify(agent) }); + setState(prev => ({ ...prev, agents: [...prev.agents, agent] })); + showToast("Agente creato", 'success'); + } catch(e) { showToast("Errore creazione agente", 'error'); } + }; + + const updateAgent = async (agent: Agent) => { + try { + await apiFetch(`/agents/${agent.id}`, { method: 'PUT', body: JSON.stringify(agent) }); + setState(prev => ({ ...prev, agents: prev.agents.map(a => a.id === agent.id ? agent : a) })); + showToast("Agente aggiornato", 'success'); + } catch(e) { showToast("Errore aggiornamento agente", 'error'); } + }; + + const removeAgent = async (id: string) => { + try { + await apiFetch(`/agents/${id}`, { method: 'DELETE' }); + setState(prev => ({ ...prev, agents: prev.agents.filter(a => a.id !== id) })); + showToast("Agente rimosso", 'info'); + } catch(e) { showToast("Errore rimozione agente", 'error'); } + }; + + const addClientUser = async (user: ClientUser) => { + // Reuses auth/register usually, but for admin adding user: + try { + await apiFetch('/auth/register', { method: 'POST', body: JSON.stringify(user) }); + setState(prev => ({ ...prev, clientUsers: [...prev.clientUsers, user] })); + showToast("Utente aggiunto", 'success'); + } catch(e) { showToast("Errore aggiunta utente", 'error'); } + }; + + const updateClientUser = async (user: ClientUser) => { + try { + await apiFetch(`/client_users/${user.id}`, { method: 'PUT', body: JSON.stringify(user) }); + setState(prev => ({ ...prev, clientUsers: prev.clientUsers.map(u => u.id === user.id ? user : u) })); + showToast("Utente aggiornato", 'success'); + } catch(e) { showToast("Errore aggiornamento utente", 'error'); } + }; + + const removeClientUser = async (id: string) => { + try { + await apiFetch(`/client_users/${id}`, { method: 'DELETE' }); + setState(prev => ({ ...prev, clientUsers: prev.clientUsers.filter(u => u.id !== id) })); + showToast("Utente rimosso", 'info'); + } catch(e) { showToast("Errore rimozione utente", 'error'); } + }; + + const updateSettings = async (newSettings: AppSettings) => { + try { + await apiFetch('/settings', { method: 'PUT', body: JSON.stringify(newSettings) }); + setState(prev => ({ ...prev, settings: newSettings })); + // Note: Real-time update of theme might require reload or context update, but setState handles it for current session + } catch(e) { showToast("Errore salvataggio impostazioni", 'error'); } + }; + + const addQueue = async (queue: TicketQueue) => { + try { + await apiFetch('/queues', { method: 'POST', body: JSON.stringify(queue) }); + setState(prev => ({ ...prev, queues: [...prev.queues, queue] })); + showToast("Coda aggiunta", 'success'); + } catch(e) { showToast("Errore aggiunta coda", 'error'); } + }; + + const removeQueue = async (id: string) => { + try { + await apiFetch(`/queues/${id}`, { method: 'DELETE' }); + setState(prev => ({ ...prev, queues: prev.queues.filter(q => q.id !== id) })); + showToast("Coda rimossa", 'info'); + } catch(e) { showToast("Errore rimozione coda", 'error'); } + }; // Render Logic