diff --git a/application/controllers/ContactController.php b/application/controllers/ContactController.php
new file mode 100644
index 0000000..17ac890
--- /dev/null
+++ b/application/controllers/ContactController.php
@@ -0,0 +1,147 @@
+email = new EmailService();
+ }
+
+ /**
+ * POST /api/contact/request-invite
+ * Raccoglie i dati del lead e invia notifica a info@agile.software
+ */
+ public function requestInvite(): void
+ {
+ // Rate limit: max 3 richieste / 10 min per IP
+ $ip = $this->getClientIP();
+ $key = 'contact_' . md5($ip);
+ $cacheFile = sys_get_temp_dir() . '/nis2_contact_' . $key;
+ $now = time();
+
+ if (file_exists($cacheFile)) {
+ $data = json_decode(file_get_contents($cacheFile), true);
+ $data['requests'] = array_filter($data['requests'] ?? [], fn($t) => $t > ($now - 600));
+ if (count($data['requests']) >= 3) {
+ $this->jsonError('Troppe richieste. Riprova tra qualche minuto.', 429);
+ return;
+ }
+ } else {
+ $data = ['requests' => []];
+ }
+ $data['requests'][] = $now;
+ file_put_contents($cacheFile, json_encode($data));
+
+ // Validazione input
+ $body = $this->getRequestBody();
+ $nome = trim($body['nome'] ?? '');
+ $email = trim($body['email'] ?? '');
+ $azienda = trim($body['azienda'] ?? '');
+ $ruolo = trim($body['ruolo'] ?? '');
+ $dimensioni = trim($body['dimensioni'] ?? '');
+ $messaggio = trim($body['messaggio'] ?? '');
+
+ if (!$nome || !$email || !$azienda || !$ruolo) {
+ $this->jsonError('Compila tutti i campi obbligatori (nome, email, azienda, ruolo).', 422);
+ return;
+ }
+ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ $this->jsonError('Indirizzo email non valido.', 422);
+ return;
+ }
+ // Sanitize
+ $nome = htmlspecialchars($nome, ENT_QUOTES, 'UTF-8');
+ $email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
+ $azienda = htmlspecialchars($azienda, ENT_QUOTES, 'UTF-8');
+ $ruolo = htmlspecialchars($ruolo, ENT_QUOTES, 'UTF-8');
+ $dimensioni = htmlspecialchars($dimensioni, ENT_QUOTES, 'UTF-8');
+ $messaggio = htmlspecialchars($messaggio, ENT_QUOTES, 'UTF-8');
+
+ $date = date('d/m/Y H:i');
+
+ $html = "
+
+
+
+ π‘οΈ Nuova richiesta codice invito β NIS2 Agile
+
+
Ricevuta il {$date}
+
+
+
+
+ | Nome |
+ {$nome} |
+
+
+ | Email |
+ {$email} |
+
+
+ | Azienda/Studio |
+ {$azienda} |
+
+
+ | Ruolo |
+ {$ruolo} |
+
+ " . ($dimensioni ? "
+
+ | Dimensioni |
+ {$dimensioni} |
+
" : "") . "
+ " . ($messaggio ? "
+
+ | Messaggio |
+ {$messaggio} |
+
" : "") . "
+
+ | IP |
+ {$ip} |
+
+
+
+
+ Rispondi a questo lead generando un codice invito da:
+ licenseExt.html
+
+
+
+
";
+
+ $sent = $this->email->send(
+ 'info@agile.software',
+ "π‘οΈ Richiesta accesso NIS2 Agile β {$nome} ({$azienda})",
+ $html,
+ 'noreply@agile.software'
+ );
+
+ if (!$sent) {
+ $this->jsonError('Errore nell\'invio della richiesta. Prova a contattarci direttamente a info@agile.software.', 500);
+ return;
+ }
+
+ $this->jsonSuccess(null, 'Richiesta inviata! Ti contatteremo entro 24 ore con il tuo codice di accesso.');
+ }
+
+ private function getClientIP(): string
+ {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
+ return trim($ips[0]);
+ }
+ return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
+ }
+}
diff --git a/public/index.html b/public/index.html
index bd533ce..4a8248d 100644
--- a/public/index.html
+++ b/public/index.html
@@ -74,6 +74,15 @@
}
.nav-name span { color: var(--cyan); }
.nav-actions { display: flex; gap: 12px; align-items: center; }
+ .btn-invite {
+ background: var(--brand-gradient);
+ color: white;
+ box-shadow: 0 4px 16px rgba(6,182,212,0.25);
+ }
+ .btn-invite:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 8px 24px rgba(6,182,212,0.35);
+ }
.btn {
display: inline-flex;
align-items: center;
@@ -531,6 +540,89 @@
}
.norma-strip i { color: var(--cyan); }
+ /* ββ BADGE INVITO ββ */
+ .invite-badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ background: rgba(245,158,11,0.1);
+ border: 1px solid rgba(245,158,11,0.25);
+ border-radius: 8px;
+ padding: 8px 16px;
+ font-size: 13px;
+ color: var(--orange);
+ margin-bottom: 20px;
+ }
+ .invite-badge i { font-size: 12px; }
+
+ /* ββ FORM LEAD ββ */
+ #richiedi-accesso { background: var(--surface-dark); }
+ .form-box {
+ background: var(--brand-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 20px;
+ padding: 48px;
+ max-width: 680px;
+ margin: 0 auto;
+ }
+ .form-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
+ margin-bottom: 20px;
+ }
+ .form-group { display: flex; flex-direction: column; gap: 8px; }
+ .form-group.full { grid-column: 1 / -1; }
+ .form-group label {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--text-light);
+ }
+ .form-group label span { color: var(--red); margin-left: 2px; }
+ .form-group input,
+ .form-group select,
+ .form-group textarea {
+ background: var(--surface-dark);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 12px 16px;
+ font-size: 14px;
+ color: var(--text-white);
+ font-family: inherit;
+ transition: border-color 0.2s;
+ width: 100%;
+ }
+ .form-group input:focus,
+ .form-group select:focus,
+ .form-group textarea:focus {
+ outline: none;
+ border-color: var(--cyan);
+ }
+ .form-group input::placeholder,
+ .form-group textarea::placeholder { color: var(--text-muted); }
+ .form-group select option { background: #1E293B; }
+ .form-group textarea { resize: vertical; min-height: 90px; }
+ .form-submit { width: 100%; padding: 14px; font-size: 16px; margin-top: 8px; }
+ .form-note { font-size: 12px; color: var(--text-muted); text-align: center; margin-top: 12px; }
+ .form-success {
+ display: none;
+ text-align: center;
+ padding: 32px;
+ }
+ .form-success i { font-size: 48px; color: var(--green); margin-bottom: 16px; display: block; }
+ .form-success h3 { font-size: 22px; font-weight: 700; color: var(--text-white); margin-bottom: 8px; }
+ .form-success p { color: var(--text-muted); font-size: 15px; }
+ .form-error-msg {
+ display: none;
+ background: rgba(239,68,68,0.08);
+ border: 1px solid rgba(239,68,68,0.2);
+ border-radius: 8px;
+ padding: 12px 16px;
+ font-size: 13px;
+ color: var(--red);
+ margin-bottom: 16px;
+ }
+
/* ββ RESPONSIVE ββ */
@media (max-width: 900px) {
nav { padding: 0 20px; }
@@ -546,6 +638,8 @@
.lg231-card { flex-direction: column; padding: 28px; }
.footer-inner { flex-direction: column; align-items: flex-start; }
.nav-actions .btn-ghost { display: none; }
+ .form-grid { grid-template-columns: 1fr; }
+ .form-box { padding: 28px 20px; }
}
@@ -561,8 +655,8 @@
Accedi
-
- Registrati
+
+ Richiedi accesso
@@ -583,12 +677,16 @@
Piattaforma SaaS multi-tenant per guidare la tua azienda alla conformitΓ con la Direttiva NIS2 (EU 2022/2555). Gap analysis AI, risk management, incident response Art.23, policy e formazione β tutto integrato.
+
+
+ Accesso su invito β Richiedi il tuo codice per iniziare
+
@@ -849,21 +947,95 @@
+
+
+
-
Inizia oggi la tua
compliance NIS2
-
Registrazione gratuita. Nessuna carta di credito richiesta. Operativo in 5 minuti.
+
La tua compliance NIS2
inizia con un codice
+
Richiedi l'accesso oggi. Nessuna carta di credito richiesta. Operativo in 5 minuti dal ricevimento del codice.
-
Hai giΓ una licenza ricevuta da un consulente? Registrati con il tuo codice invito
+
Sei un consulente o MSSP? Il form di richiesta ti permette di attivare accesso per il tuo intero portfolio clienti.
@@ -877,8 +1049,8 @@
by Agile Technology SRL
@@ -888,5 +1060,51 @@
+