From ab5cf6752f415e15570e8b3ff4d8d1f37f4c6db1 Mon Sep 17 00:00:00 2001 From: fcarraUniSa Date: Tue, 17 Feb 2026 14:24:38 +0100 Subject: [PATCH] Update index.js --- backend/index.js | 62 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/backend/index.js b/backend/index.js index 394fcc7..5f7b873 100644 --- a/backend/index.js +++ b/backend/index.js @@ -2,12 +2,41 @@ import express from 'express'; import cors from 'cors'; import { checkConnection, query, initDb } from './db.js'; import { randomUUID } from 'crypto'; +import multer from 'multer'; +import path from 'path'; +import fs from 'fs'; +import { fileURLToPath } from 'url'; const app = express(); const PORT = process.env.PORT || 3000; +// Fix per __dirname in ES Modules +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Ensure uploads directory exists +const uploadDir = path.join(__dirname, 'uploads'); +if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }); +} + +// Multer Configuration +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, uploadDir) + }, + filename: function (req, file, cb) { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9) + cb(null, uniqueSuffix + '-' + file.originalname) + } +}) + +const upload = multer({ storage: storage }); + app.use(cors()); app.use(express.json()); +// Serve uploaded files statically +app.use('/uploads', express.static(uploadDir)); // --- HELPER FUNCTIONS --- const safeJsonParse = (val, fallback) => { @@ -159,6 +188,24 @@ app.get('/api/initial-data', async (req, res) => { } }); +// --- UPLOAD ENDPOINT --- +app.post('/api/upload', upload.single('file'), (req, res) => { + if (!req.file) { + return res.status(400).json({ error: 'Nessun file caricato' }); + } + + // Construct absolute URL for the file + // In prod, this would be S3 url or similar + const fileUrl = `/api/uploads/${req.file.filename}`; + + res.json({ + id: req.file.filename, + name: req.file.originalname, + url: fileUrl, + type: req.file.mimetype + }); +}); + // --- TICKET ENDPOINTS --- app.get('/api/tickets', async (req, res) => { @@ -176,7 +223,8 @@ app.get('/api/tickets', async (req, res) => { 'id', m.id, 'role', m.role, 'content', m.content, - 'timestamp', m.timestamp + 'timestamp', m.timestamp, + 'attachments', m.attachments ) ) FROM ticket_messages m @@ -192,7 +240,10 @@ app.get('/api/tickets', async (req, res) => { ...t, hasBeenAnalyzed: !!t.hasBeenAnalyzed, // Cast to boolean attachments: safeJsonParse(t.attachments, []), - messages: safeJsonParse(t.messages, []) + messages: safeJsonParse(t.messages, []).map(m => ({ + ...m, + attachments: safeJsonParse(m.attachments, []) + })) })); res.json(tickets); @@ -276,13 +327,13 @@ app.post('/api/tickets/mark-analyzed', async (req, res) => { app.post('/api/tickets/:id/messages', async (req, res) => { const { id } = req.params; - const { role, content } = req.body; + const { role, content, attachments } = req.body; const messageId = `m-${Date.now()}`; try { await query( - 'INSERT INTO ticket_messages (id, ticket_id, role, content) VALUES (?, ?, ?, ?)', - [messageId, id, role, content] + 'INSERT INTO ticket_messages (id, ticket_id, role, content, attachments) VALUES (?, ?, ?, ?, ?)', + [messageId, id, role, content, JSON.stringify(attachments || [])] ); if (role === 'user') { @@ -293,6 +344,7 @@ app.post('/api/tickets/:id/messages', async (req, res) => { id: messageId, role, content, + attachments: attachments || [], timestamp: new Date().toISOString() }); } catch (e) {