diff --git a/backend/index.js b/backend/index.js index 945940b..70125d9 100644 --- a/backend/index.js +++ b/backend/index.js @@ -57,6 +57,47 @@ app.post('/api/auth/register', async (req, res) => { } }); +// --- SETTINGS ENDPOINTS --- + +app.get('/api/settings', async (req, res) => { + try { + const rows = await query('SELECT * FROM settings WHERE id = 1'); + if (rows.length === 0) return res.status(404).json({ error: 'Settings not found' }); + + const s = rows[0]; + const settings = { + branding: typeof s.branding === 'string' ? JSON.parse(s.branding) : s.branding, + smtp: typeof s.smtp === 'string' ? JSON.parse(s.smtp) : s.smtp, + emailTemplates: typeof s.email_templates === 'string' ? JSON.parse(s.email_templates) : s.email_templates, + features: typeof s.features === 'string' ? JSON.parse(s.features) : s.features, + aiConfig: typeof s.ai_config === 'string' ? JSON.parse(s.ai_config) : s.ai_config + }; + res.json(settings); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.put('/api/settings', async (req, res) => { + const { branding, smtp, emailTemplates, features, aiConfig } = req.body; + try { + await query( + 'UPDATE settings SET branding=?, smtp=?, email_templates=?, features=?, ai_config=? WHERE id=1', + [ + JSON.stringify(branding), + JSON.stringify(smtp), + JSON.stringify(emailTemplates), + JSON.stringify(features), + JSON.stringify(aiConfig) + ] + ); + res.json({ success: true }); + } catch (e) { + console.error("Error saving settings:", e); + res.status(500).json({ error: e.message }); + } +}); + // --- DATA FETCHING ENDPOINTS --- app.get('/api/initial-data', async (req, res) => { @@ -82,12 +123,27 @@ app.get('/api/initial-data', async (req, res) => { // Fetch Surveys const surveys = await query('SELECT * FROM survey_results ORDER BY timestamp DESC'); + // Fetch Settings + let settings = null; + const settingsRows = await query('SELECT * FROM settings WHERE id = 1'); + if (settingsRows.length > 0) { + const s = settingsRows[0]; + settings = { + branding: typeof s.branding === 'string' ? JSON.parse(s.branding) : s.branding, + smtp: typeof s.smtp === 'string' ? JSON.parse(s.smtp) : s.smtp, + emailTemplates: typeof s.email_templates === 'string' ? JSON.parse(s.email_templates) : s.email_templates, + features: typeof s.features === 'string' ? JSON.parse(s.features) : s.features, + aiConfig: typeof s.ai_config === 'string' ? JSON.parse(s.ai_config) : s.ai_config + }; + } + res.json({ agents: parsedAgents, clientUsers, queues, articles, - surveys + surveys, + settings }); } catch (e) { console.error(e); @@ -99,8 +155,6 @@ app.get('/api/initial-data', async (req, res) => { app.get('/api/tickets', async (req, res) => { try { - // Complex query to get tickets + messages + attachments - // Note: We use a subquery or JSON_ARRAYAGG to bundle messages const sql = ` SELECT t.*, @@ -140,7 +194,7 @@ app.get('/api/tickets', async (req, res) => { app.post('/api/tickets', async (req, res) => { const { subject, description, priority, queue, customerName, attachments } = req.body; - const id = `T-${Date.now()}`; // Generate a simple ID or UUID + const id = `T-${Date.now()}`; try { await query( @@ -148,7 +202,6 @@ app.post('/api/tickets', async (req, res) => { [id, subject, description, 'APERTO', priority, customerName, queue, JSON.stringify(attachments || [])] ); - // Fetch the created ticket to return it const newTicket = { id, subject, @@ -181,7 +234,7 @@ app.patch('/api/tickets/:id', async (req, res) => { if (updates.assignedAgentId !== undefined) { fields.push('assigned_agent_id = ?'); values.push(updates.assignedAgentId || null); } if (updates.queue) { fields.push('queue = ?'); values.push(updates.queue); } - if (fields.length === 0) return res.json({ success: true }); // Nothing to update + if (fields.length === 0) return res.json({ success: true }); values.push(id); @@ -193,10 +246,8 @@ app.patch('/api/tickets/:id', async (req, res) => { } }); -// --- MESSAGING ENDPOINTS --- - app.post('/api/tickets/:id/messages', async (req, res) => { - const { id } = req.params; // Ticket ID + const { id } = req.params; const { role, content } = req.body; const messageId = `m-${Date.now()}`; @@ -206,7 +257,6 @@ app.post('/api/tickets/:id/messages', async (req, res) => { [messageId, id, role, content] ); - // Se il messaggio รจ dell'utente e il ticket era risolto, riapriamolo if (role === 'user') { await query("UPDATE tickets SET status = 'APERTO' WHERE id = ? AND status = 'RISOLTO'", [id]); } @@ -222,7 +272,98 @@ app.post('/api/tickets/:id/messages', async (req, res) => { } }); -// --- SURVEY ENDPOINTS --- +// --- MANAGEMENT ENDPOINTS (Agents, Users, Queues) --- + +app.post('/api/agents', async (req, res) => { + const agent = req.body; + try { + await query( + 'INSERT INTO agents (id, name, email, password, role, avatar, avatar_config, skills, queues) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', + [ + agent.id, agent.name, agent.email, agent.password, agent.role, agent.avatar, + JSON.stringify(agent.avatarConfig || {}), + JSON.stringify(agent.skills || []), + JSON.stringify(agent.queues || []) + ] + ); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.put('/api/agents/:id', async (req, res) => { + const { id } = req.params; + const agent = req.body; + try { + await query( + 'UPDATE agents SET name=?, email=?, password=?, role=?, avatar=?, avatar_config=?, skills=?, queues=? WHERE id=?', + [ + agent.name, agent.email, agent.password, agent.role, agent.avatar, + JSON.stringify(agent.avatarConfig), + JSON.stringify(agent.skills), + JSON.stringify(agent.queues), + id + ] + ); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.delete('/api/agents/:id', async (req, res) => { + try { + await query('DELETE FROM agents WHERE id = ?', [req.params.id]); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.put('/api/client_users/:id', async (req, res) => { + const { id } = req.params; + const { name, email, company, status } = req.body; + try { + await query( + 'UPDATE client_users SET name=?, email=?, company=?, status=? WHERE id=?', + [name, email, company, status, id] + ); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.delete('/api/client_users/:id', async (req, res) => { + try { + await query('DELETE FROM client_users WHERE id = ?', [req.params.id]); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.post('/api/queues', async (req, res) => { + const { id, name, description } = req.body; + try { + await query('INSERT INTO queues (id, name, description) VALUES (?, ?, ?)', [id, name, description]); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +app.delete('/api/queues/:id', async (req, res) => { + try { + await query('DELETE FROM queues WHERE id = ?', [req.params.id]); + res.json({ success: true }); + } catch (e) { + res.status(500).json({ error: e.message }); + } +}); + +// --- SURVEY & KB ENDPOINTS --- app.post('/api/surveys', async (req, res) => { const { rating, comment, source, referenceId } = req.body; const id = randomUUID(); @@ -237,7 +378,6 @@ app.post('/api/surveys', async (req, res) => { } }); -// --- KB ENDPOINTS --- app.post('/api/articles', async (req, res) => { const { title, content, category, type, url, source } = req.body; const id = `kb-${Date.now()}`; @@ -266,10 +406,8 @@ app.patch('/api/articles/:id', async (req, res) => { } }); -// Avvio del server const startServer = async () => { await initDb(); - app.listen(PORT, () => { console.log(`๐Ÿš€ Backend Server running on port ${PORT}`); checkConnection();