[FEAT] Sistema Segnalazioni & Risoluzione AI (feedback)

Adattato da alltax.it — il sistema più maturo testato con utenti reali.

Backend:
- FeedbackController: 6 endpoint (submit, mine, list, show, update, resolve)
- FeedbackService: createReport + classifyWithAI + broadcastResolution
- AIService::classifyFeedback() — 10s timeout, 500 token, JSON puro
- EmailService::sendFeedbackResolved() — broadcast email org
- DB migration 014: tabella feedback_reports

Frontend:
- feedback.js: FAB rosso #EF4444, modal 2 fasi (form → AI → password gate)
- Tab "Le mie segnalazioni" con badge status
- Auto-init su tutte le pagine autenticate (common.js::checkAuth)
- api.js: 6 metodi client; style.css: stili completi

Worker:
- scripts/feedback-worker.php: cron ogni 30 min
  → docker exec nis2-agile-devenv + Claude Code CLI
  → risoluzione autonoma con POST /api/feedback/{id}/resolve

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-03-10 08:51:52 +01:00
co-authored by Claude Sonnet 4.6
parent 3b51b5bd95
commit 1382530189
13 changed files with 1911 additions and 43 deletions
+42
View File
@@ -524,6 +524,48 @@ class EmailService
$this->send($user['email'], $subject, $html);
}
// ═══════════════════════════════════════════════════════════════════════════
// FEEDBACK & SEGNALAZIONI
// ═══════════════════════════════════════════════════════════════════════════
/**
* Broadcast risoluzione segnalazione a un membro dell'org
*
* @param string $to Email destinatario
* @param string $reportTitle Titolo breve della segnalazione
* @param string $resolution Testo risoluzione (nota admin o risposta AI)
*/
public function sendFeedbackResolved(string $to, string $reportTitle, string $resolution): bool
{
$html = <<<HTML
<div style="background-color: #f0fdf4; border-left: 4px solid #16a34a; padding: 16px; margin-bottom: 24px; border-radius: 4px;">
<strong style="color: #16a34a; font-size: 16px;">&#10003; Segnalazione Risolta</strong><br>
<span style="color: #166534;">Il problema segnalato &egrave; stato risolto</span>
</div>
<p>Una segnalazione nella tua organizzazione &egrave; stata risolta:</p>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<tr style="background-color: #f8fafc;">
<td style="padding: 10px 14px; border: 1px solid #e2e8f0; font-weight: 600; width: 160px;">Segnalazione</td>
<td style="padding: 10px 14px; border: 1px solid #e2e8f0;">{$this->esc($reportTitle)}</td>
</tr>
<tr>
<td style="padding: 10px 14px; border: 1px solid #e2e8f0; font-weight: 600;">Risoluzione</td>
<td style="padding: 10px 14px; border: 1px solid #e2e8f0; line-height: 1.6;">{$this->esc($resolution)}</td>
</tr>
</table>
<p style="margin-top: 20px;">
<a href="{$this->esc($this->appUrl)}/dashboard" style="display: inline-block; background-color: #ef4444; color: #ffffff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: 600;">Vai alla Dashboard</a>
</p>
HTML;
$subject = "&#10003; Risolto: {$reportTitle}";
return $this->send($to, $subject, $html);
}
// ═══════════════════════════════════════════════════════════════════════════
// TEMPLATE HTML
// ═══════════════════════════════════════════════════════════════════════════