login.html: eye toggle, forgot password, auth-terms footer register.html: wizard 3-step, 5 ruoli NIS2, invite_token URL, P.IVA lookup onboarding.html: Font Awesome, brand color cyan (#06B6D4) test-runner.php: L1-L5 test levels, SIM-06 B2B, tab Coverage/Stats, DB row counts, run history (localStorage), 5 tabs totali Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1761 lines
80 KiB
HTML
1761 lines
80 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Onboarding - NIS2 Agile</title>
|
|
<link rel="stylesheet" href="css/style.css">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
<style>
|
|
/* NIS2 brand color override for wizard */
|
|
:root { --nis2-cyan: #06B6D4; --nis2-cyan-light: #ecfeff; --nis2-cyan-ring: rgba(6,182,212,.15); }
|
|
/* ── Wizard Layout ──────────────────────────────────────────── */
|
|
.wizard-page {
|
|
min-height: 100vh;
|
|
background: var(--gray-50);
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.wizard-header {
|
|
background: var(--card-bg);
|
|
border-bottom: 1px solid var(--gray-200);
|
|
padding: 16px 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.wizard-header-logo {
|
|
width: 36px;
|
|
height: 36px;
|
|
background: var(--primary);
|
|
border-radius: var(--border-radius);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.wizard-header-logo svg {
|
|
width: 20px;
|
|
height: 20px;
|
|
fill: #fff;
|
|
}
|
|
|
|
.wizard-header-text h1 {
|
|
font-size: 1.125rem;
|
|
font-weight: 700;
|
|
color: var(--gray-900);
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.wizard-header-text span {
|
|
font-size: 0.7rem;
|
|
color: var(--gray-500);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
/* ── Stepper ────────────────────────────────────────────────── */
|
|
.wizard-stepper {
|
|
background: var(--card-bg);
|
|
border-bottom: 1px solid var(--gray-200);
|
|
padding: 20px 32px;
|
|
}
|
|
|
|
.stepper {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0;
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.stepper-step {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.stepper-number {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
background: var(--gray-200);
|
|
color: var(--gray-500);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.8rem;
|
|
font-weight: 700;
|
|
flex-shrink: 0;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.stepper-label {
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
color: var(--gray-400);
|
|
transition: color var(--transition);
|
|
}
|
|
|
|
.stepper-step.active .stepper-number {
|
|
background: var(--nis2-cyan);
|
|
color: #fff;
|
|
box-shadow: 0 0 0 4px var(--nis2-cyan-ring);
|
|
}
|
|
|
|
.stepper-step.active .stepper-label {
|
|
color: var(--nis2-cyan);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.stepper-step.completed .stepper-number {
|
|
background: var(--nis2-cyan);
|
|
color: #fff;
|
|
}
|
|
|
|
.stepper-step.completed .stepper-label {
|
|
color: var(--nis2-cyan);
|
|
}
|
|
|
|
.stepper-connector {
|
|
width: 40px;
|
|
height: 2px;
|
|
background: var(--gray-200);
|
|
margin: 0 8px;
|
|
flex-shrink: 0;
|
|
transition: background var(--transition);
|
|
}
|
|
|
|
.stepper-connector.completed {
|
|
background: var(--nis2-cyan);
|
|
}
|
|
|
|
/* ── Wizard Body ────────────────────────────────────────────── */
|
|
.wizard-body {
|
|
flex: 1;
|
|
display: flex;
|
|
justify-content: center;
|
|
padding: 40px 24px 60px;
|
|
}
|
|
|
|
.wizard-content {
|
|
width: 100%;
|
|
max-width: 800px;
|
|
}
|
|
|
|
/* ── Step Panels ────────────────────────────────────────────── */
|
|
.wizard-step {
|
|
display: none;
|
|
animation: wizardFadeIn 0.35s ease;
|
|
}
|
|
|
|
.wizard-step.active {
|
|
display: block;
|
|
}
|
|
|
|
@keyframes wizardFadeIn {
|
|
from { opacity: 0; transform: translateY(12px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.wizard-step-title {
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
color: var(--gray-900);
|
|
margin-bottom: 8px;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.wizard-step-subtitle {
|
|
font-size: 0.9375rem;
|
|
color: var(--gray-500);
|
|
margin-bottom: 32px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* ── Option Cards (Step 1) ──────────────────────────────────── */
|
|
.option-cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 20px;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.option-card {
|
|
background: var(--card-bg);
|
|
border: 2px solid var(--gray-200);
|
|
border-radius: var(--border-radius-lg);
|
|
padding: 28px 24px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all var(--transition);
|
|
position: relative;
|
|
}
|
|
|
|
.option-card:hover {
|
|
border-color: var(--primary-light);
|
|
box-shadow: var(--card-shadow-hover);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.option-card.selected {
|
|
border-color: var(--nis2-cyan);
|
|
background: var(--nis2-cyan-light);
|
|
box-shadow: 0 0 0 4px var(--nis2-cyan-ring);
|
|
}
|
|
|
|
.option-card-icon {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: var(--border-radius-lg);
|
|
background: var(--primary-bg);
|
|
color: var(--primary);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto 16px;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.option-card.selected .option-card-icon {
|
|
background: var(--nis2-cyan);
|
|
color: #fff;
|
|
}
|
|
|
|
.option-card-icon svg {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
|
|
.option-card-title {
|
|
font-size: 0.9375rem;
|
|
font-weight: 700;
|
|
color: var(--gray-900);
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.option-card-desc {
|
|
font-size: 0.8125rem;
|
|
color: var(--gray-500);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.option-card-check {
|
|
position: absolute;
|
|
top: 12px;
|
|
right: 12px;
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
background: var(--primary);
|
|
color: #fff;
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.option-card.selected .option-card-check {
|
|
display: flex;
|
|
}
|
|
|
|
.option-card-check svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
/* ── Upload Area ────────────────────────────────────────────── */
|
|
.upload-area {
|
|
border: 2px dashed var(--gray-300);
|
|
border-radius: var(--border-radius-lg);
|
|
padding: 48px 24px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all var(--transition);
|
|
background: var(--card-bg);
|
|
position: relative;
|
|
}
|
|
|
|
.upload-area:hover,
|
|
.upload-area.dragover {
|
|
border-color: var(--primary);
|
|
background: var(--primary-bg);
|
|
}
|
|
|
|
.upload-area.has-file {
|
|
border-color: var(--secondary);
|
|
background: var(--secondary-bg);
|
|
border-style: solid;
|
|
}
|
|
|
|
.upload-area-icon {
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 50%;
|
|
background: var(--gray-100);
|
|
color: var(--gray-400);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto 16px;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.upload-area:hover .upload-area-icon,
|
|
.upload-area.dragover .upload-area-icon {
|
|
background: var(--primary);
|
|
color: #fff;
|
|
}
|
|
|
|
.upload-area.has-file .upload-area-icon {
|
|
background: var(--secondary);
|
|
color: #fff;
|
|
}
|
|
|
|
.upload-area-icon svg {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
|
|
.upload-area-title {
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
color: var(--gray-700);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.upload-area-hint {
|
|
font-size: 0.8125rem;
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
.upload-area-formats {
|
|
font-size: 0.75rem;
|
|
color: var(--gray-400);
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.upload-file-info {
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
margin-top: 12px;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
color: var(--secondary);
|
|
}
|
|
|
|
.upload-file-info svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
}
|
|
|
|
.upload-area.has-file .upload-file-info {
|
|
display: flex;
|
|
}
|
|
|
|
.upload-area input[type="file"] {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* ── Loading State ──────────────────────────────────────────── */
|
|
.wizard-loading {
|
|
display: none;
|
|
text-align: center;
|
|
padding: 48px 24px;
|
|
}
|
|
|
|
.wizard-loading.active {
|
|
display: block;
|
|
}
|
|
|
|
.wizard-loading .spinner-lg {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.wizard-loading-text {
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
color: var(--gray-700);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.wizard-loading-subtext {
|
|
font-size: 0.8125rem;
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
/* ── CertiSource Badge ──────────────────────────────────────── */
|
|
.certisource-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 6px 14px;
|
|
background: var(--gray-50);
|
|
border: 1px solid var(--gray-200);
|
|
border-radius: 100px;
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--gray-600);
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.certisource-badge svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
color: var(--primary);
|
|
}
|
|
|
|
/* ── Data Source Banner ──────────────────────────────────────── */
|
|
.data-source-banner {
|
|
display: none;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 12px 20px;
|
|
background: var(--secondary-bg);
|
|
border: 1px solid #bbf7d0;
|
|
border-radius: var(--border-radius);
|
|
margin-bottom: 24px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
color: #15803d;
|
|
}
|
|
|
|
.data-source-banner.visible {
|
|
display: flex;
|
|
}
|
|
|
|
.data-source-banner svg {
|
|
width: 20px;
|
|
height: 20px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ── Company Form Grid ──────────────────────────────────────── */
|
|
.form-grid-2 {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 0 20px;
|
|
}
|
|
|
|
.form-grid-2 .form-group-full {
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
/* ── Profile Form ───────────────────────────────────────────── */
|
|
.profile-form-wrapper {
|
|
max-width: 520px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* ── Classification Result (Step 5) ─────────────────────────── */
|
|
.classification-result {
|
|
padding: 32px;
|
|
border-radius: var(--border-radius-lg);
|
|
border: 2px solid var(--gray-200);
|
|
text-align: center;
|
|
margin-bottom: 24px;
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.classification-result.essential {
|
|
border-color: #1e40af;
|
|
background: linear-gradient(135deg, #eff6ff, #dbeafe);
|
|
}
|
|
|
|
.classification-result.important {
|
|
border-color: #d97706;
|
|
background: linear-gradient(135deg, #fffbeb, #fef3c7);
|
|
}
|
|
|
|
.classification-result.not-applicable {
|
|
border-color: var(--gray-300);
|
|
background: var(--gray-50);
|
|
}
|
|
|
|
.classification-result-icon {
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto 16px;
|
|
}
|
|
|
|
.classification-result.essential .classification-result-icon {
|
|
background: #1e40af;
|
|
color: #fff;
|
|
}
|
|
|
|
.classification-result.important .classification-result-icon {
|
|
background: #d97706;
|
|
color: #fff;
|
|
}
|
|
|
|
.classification-result.not-applicable .classification-result-icon {
|
|
background: var(--gray-300);
|
|
color: #fff;
|
|
}
|
|
|
|
.classification-result-icon svg {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
|
|
.classification-result-label {
|
|
font-size: 1.5rem;
|
|
font-weight: 800;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.classification-result.essential .classification-result-label {
|
|
color: #1e40af;
|
|
}
|
|
|
|
.classification-result.important .classification-result-label {
|
|
color: #d97706;
|
|
}
|
|
|
|
.classification-result.not-applicable .classification-result-label {
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
.classification-result-desc {
|
|
font-size: 0.875rem;
|
|
color: var(--gray-600);
|
|
line-height: 1.6;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* ── Summary Card ───────────────────────────────────────────── */
|
|
.summary-card {
|
|
background: var(--card-bg);
|
|
border-radius: var(--border-radius-lg);
|
|
box-shadow: var(--card-shadow);
|
|
overflow: hidden;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.summary-card-header {
|
|
padding: 16px 24px;
|
|
border-bottom: 1px solid var(--gray-100);
|
|
font-size: 0.9375rem;
|
|
font-weight: 600;
|
|
color: var(--gray-900);
|
|
}
|
|
|
|
.summary-card-body {
|
|
padding: 24px;
|
|
}
|
|
|
|
.summary-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 16px;
|
|
}
|
|
|
|
.summary-item {
|
|
padding: 8px 0;
|
|
}
|
|
|
|
.summary-item-label {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
color: var(--gray-500);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.summary-item-value {
|
|
font-size: 0.9375rem;
|
|
font-weight: 500;
|
|
color: var(--gray-800);
|
|
}
|
|
|
|
/* ── Wizard Footer/Actions ──────────────────────────────────── */
|
|
.wizard-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding-top: 32px;
|
|
border-top: 1px solid var(--gray-200);
|
|
margin-top: 32px;
|
|
}
|
|
|
|
.wizard-actions-right {
|
|
display: flex;
|
|
gap: 12px;
|
|
}
|
|
|
|
/* ── Auto-fill indicators ──────────────────────────────────── */
|
|
.auto-filled .form-input,
|
|
.auto-filled .form-select {
|
|
border-color: #86efac;
|
|
background: #f0fdf4;
|
|
}
|
|
|
|
.auto-fill-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 2px 8px;
|
|
margin-left: 8px;
|
|
font-size: 0.65rem;
|
|
font-weight: 600;
|
|
color: #15803d;
|
|
background: #dcfce7;
|
|
border-radius: 100px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.03em;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
/* ── Voluntary Compliance ──────────────────────────────────── */
|
|
.voluntary-section {
|
|
display: none;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.voluntary-section.visible {
|
|
display: block;
|
|
}
|
|
|
|
.voluntary-card {
|
|
border: 2px solid var(--primary-light);
|
|
border-radius: var(--border-radius-lg);
|
|
padding: 24px;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 16px;
|
|
background: var(--card-bg);
|
|
transition: all var(--transition);
|
|
}
|
|
|
|
.voluntary-card.checked {
|
|
border-color: var(--primary);
|
|
background: var(--primary-bg);
|
|
}
|
|
|
|
.voluntary-card input[type="checkbox"] {
|
|
width: 20px;
|
|
height: 20px;
|
|
cursor: pointer;
|
|
accent-color: var(--primary);
|
|
flex-shrink: 0;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.voluntary-card h4 {
|
|
font-size: 0.9375rem;
|
|
font-weight: 700;
|
|
color: var(--gray-900);
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.voluntary-card p {
|
|
font-size: 0.8125rem;
|
|
color: var(--gray-600);
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
}
|
|
|
|
.classification-result.voluntary {
|
|
border-color: var(--primary);
|
|
background: linear-gradient(135deg, #eff6ff, #dbeafe);
|
|
}
|
|
|
|
.classification-result.voluntary .classification-result-icon {
|
|
background: var(--primary);
|
|
color: #fff;
|
|
}
|
|
|
|
.classification-result.voluntary .classification-result-label {
|
|
color: var(--primary);
|
|
}
|
|
|
|
/* ── Responsive ─────────────────────────────────────────────── */
|
|
@media (max-width: 768px) {
|
|
.wizard-header {
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.wizard-stepper {
|
|
padding: 16px;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.stepper {
|
|
min-width: 600px;
|
|
}
|
|
|
|
.stepper-label {
|
|
display: none;
|
|
}
|
|
|
|
.wizard-body {
|
|
padding: 24px 16px 40px;
|
|
}
|
|
|
|
.option-cards {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.form-grid-2 {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.summary-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.wizard-step-title {
|
|
font-size: 1.25rem;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="wizard-page">
|
|
<!-- Header -->
|
|
<div class="wizard-header">
|
|
<div class="wizard-header-logo">
|
|
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 2.18l7 3.12v4.7c0 4.83-3.23 9.36-7 10.57-3.77-1.21-7-5.74-7-10.57V6.3l7-3.12z"/>
|
|
<path d="M10 12.5l-2-2-1.41 1.41L10 15.32l5.41-5.41L14 8.5l-4 4z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="wizard-header-text">
|
|
<h1>NIS2 Agile</h1>
|
|
<span>Configurazione Iniziale</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stepper -->
|
|
<div class="wizard-stepper">
|
|
<div class="stepper" id="stepper">
|
|
<div class="stepper-step active" data-step="1">
|
|
<div class="stepper-number">1</div>
|
|
<span class="stepper-label">Partita IVA</span>
|
|
</div>
|
|
<div class="stepper-connector" data-after="1"></div>
|
|
<div class="stepper-step" data-step="2">
|
|
<div class="stepper-number">2</div>
|
|
<span class="stepper-label">Dati Aziendali</span>
|
|
</div>
|
|
<div class="stepper-connector" data-after="2"></div>
|
|
<div class="stepper-step" data-step="3">
|
|
<div class="stepper-number">3</div>
|
|
<span class="stepper-label">Il Tuo Profilo</span>
|
|
</div>
|
|
<div class="stepper-connector" data-after="3"></div>
|
|
<div class="stepper-step" data-step="4">
|
|
<div class="stepper-number">4</div>
|
|
<span class="stepper-label">Classificazione</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wizard Body -->
|
|
<div class="wizard-body">
|
|
<div class="wizard-content">
|
|
|
|
<!-- ═══ STEP 1: Partita IVA ═══ -->
|
|
<div class="wizard-step active" id="step-1">
|
|
<h2 class="wizard-step-title">Inserisci la Partita IVA dell'azienda</h2>
|
|
<p class="wizard-step-subtitle">Inserisci la Partita IVA dell'azienda da configurare. I dati verranno recuperati automaticamente dal registro delle imprese.</p>
|
|
|
|
<div class="card" style="max-width:520px; margin:0 auto;">
|
|
<div class="card-body">
|
|
<div class="form-group">
|
|
<label class="form-label" for="s1-vat">Partita IVA <span class="required">*</span></label>
|
|
<div style="display:flex; gap:.5rem;">
|
|
<span style="display:flex;align-items:center;padding:0 12px;background:var(--gray-100);border:1px solid var(--gray-300);border-radius:var(--border-radius);font-weight:600;color:var(--gray-600);">IT</span>
|
|
<input type="text" id="s1-vat" class="form-input" placeholder="12345678901" maxlength="11"
|
|
style="flex:1;" oninput="this.value=this.value.replace(/\D/g,'')">
|
|
</div>
|
|
<div class="form-help">11 cifre numeriche senza prefisso IT</div>
|
|
</div>
|
|
|
|
<div id="s1-result" style="display:none; padding:.75rem; border-radius:8px; margin-bottom:1rem;"></div>
|
|
|
|
<button class="btn btn-primary btn-lg w-full" id="s1-fetch-btn" onclick="step1FetchCompany()">
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/></svg>
|
|
Cerca Azienda
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="wizard-loading" id="s1-loading">
|
|
<div class="spinner spinner-lg"></div>
|
|
<div class="wizard-loading-text">Ricerca in corso...</div>
|
|
<div class="wizard-loading-subtext">Interrogazione registro imprese</div>
|
|
</div>
|
|
|
|
<div style="text-align:center; margin-top:1.5rem;">
|
|
<button class="btn btn-link" onclick="step1ManualEntry()" style="color:var(--gray-500);font-size:.85rem;">
|
|
Non trovi l'azienda? Inserisci manualmente
|
|
</button>
|
|
</div>
|
|
|
|
<div class="wizard-actions" style="margin-top:2rem;">
|
|
<div></div>
|
|
<div class="wizard-actions-right">
|
|
<button class="btn btn-primary btn-lg" id="s1-continue-btn" onclick="goToStep(2)" style="display:none;">
|
|
Continua
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ STEP 3: Dati Aziendali ═══ -->
|
|
<div class="wizard-step" id="step-2">
|
|
<h2 class="wizard-step-title">Verifica e Completa i Dati Aziendali</h2>
|
|
<p class="wizard-step-subtitle">Controlla i dati qui sotto e completa le informazioni mancanti.</p>
|
|
|
|
<div class="data-source-banner" id="data-source-banner">
|
|
<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
|
|
<span id="data-source-text"></span>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="form-grid-2">
|
|
<div class="form-group form-group-full">
|
|
<label class="form-label" for="company-name">Ragione Sociale <span class="required">*</span></label>
|
|
<input type="text" id="company-name" class="form-input" placeholder="Es. Acme S.r.l." required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="vat-number">Partita IVA</label>
|
|
<input type="text" id="vat-number" class="form-input" placeholder="IT12345678901" maxlength="16">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="fiscal-code">Codice Fiscale</label>
|
|
<input type="text" id="fiscal-code" class="form-input" placeholder="Es. 12345678901" maxlength="16">
|
|
</div>
|
|
|
|
<div class="form-group form-group-full">
|
|
<label class="form-label" for="address">Indirizzo</label>
|
|
<input type="text" id="address" class="form-input" placeholder="Via Roma, 1">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="city">Citta'</label>
|
|
<input type="text" id="city" class="form-input" placeholder="Es. Milano">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="website">Sito Web</label>
|
|
<input type="text" id="website" class="form-input" placeholder="https://www.esempio.it">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="company-email">Email Aziendale</label>
|
|
<input type="email" id="company-email" class="form-input" placeholder="info@azienda.it">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="company-phone">Telefono Aziendale</label>
|
|
<input type="text" id="company-phone" class="form-input" placeholder="+39 02 1234567">
|
|
</div>
|
|
|
|
<div class="form-group form-group-full">
|
|
<label class="form-label" for="sector">Settore NIS2 <span class="required">*</span></label>
|
|
<select id="sector" class="form-select" required>
|
|
<option value="">-- Seleziona settore --</option>
|
|
<optgroup label="Settori ad Alta Criticita' (Allegato I)">
|
|
<option value="energy_electricity">Energia - Elettricita'</option>
|
|
<option value="energy_district_heating">Energia - Teleriscaldamento</option>
|
|
<option value="energy_oil">Energia - Petrolio</option>
|
|
<option value="energy_gas">Energia - Gas</option>
|
|
<option value="energy_hydrogen">Energia - Idrogeno</option>
|
|
<option value="transport_air">Trasporti - Aereo</option>
|
|
<option value="transport_rail">Trasporti - Ferroviario</option>
|
|
<option value="transport_water">Trasporti - Marittimo/Fluviale</option>
|
|
<option value="transport_road">Trasporti - Stradale</option>
|
|
<option value="banking">Banche</option>
|
|
<option value="financial_markets">Infrastrutture Mercati Finanziari</option>
|
|
<option value="health">Sanita'</option>
|
|
<option value="drinking_water">Acqua Potabile</option>
|
|
<option value="waste_water">Acque Reflue</option>
|
|
<option value="digital_infrastructure">Infrastruttura Digitale</option>
|
|
<option value="ict_service_management">Gestione Servizi ICT (B2B)</option>
|
|
<option value="public_administration">Pubblica Amministrazione</option>
|
|
<option value="space">Spazio</option>
|
|
</optgroup>
|
|
<optgroup label="Altri Settori Critici (Allegato II)">
|
|
<option value="postal_courier">Servizi Postali e Corrieri</option>
|
|
<option value="waste_management">Gestione Rifiuti</option>
|
|
<option value="chemicals">Fabbricazione Prodotti Chimici</option>
|
|
<option value="food">Produzione e Distribuzione Alimentare</option>
|
|
<option value="manufacturing_medical">Fabbricazione - Dispositivi Medici</option>
|
|
<option value="manufacturing_computers">Fabbricazione - Computer/Elettronica</option>
|
|
<option value="manufacturing_electrical">Fabbricazione - Apparecchiature Elettriche</option>
|
|
<option value="manufacturing_machinery">Fabbricazione - Macchinari</option>
|
|
<option value="manufacturing_vehicles">Fabbricazione - Autoveicoli</option>
|
|
<option value="manufacturing_transport">Fabbricazione - Altri Mezzi di Trasporto</option>
|
|
<option value="digital_providers">Fornitori Servizi Digitali</option>
|
|
<option value="research">Organizzazioni di Ricerca</option>
|
|
</optgroup>
|
|
<optgroup label="Altro">
|
|
<option value="other">Altro Settore</option>
|
|
</optgroup>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="employee-count">Numero Dipendenti <span class="required">*</span></label>
|
|
<input type="number" id="employee-count" class="form-input" placeholder="Es. 150" min="1" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="annual-turnover">Fatturato Annuo EUR <span class="required">*</span></label>
|
|
<input type="number" id="annual-turnover" class="form-input" placeholder="Es. 15000000" min="0" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="wizard-actions">
|
|
<button class="btn btn-secondary" onclick="goToStep(1)">
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd"/></svg>
|
|
Indietro
|
|
</button>
|
|
<div class="wizard-actions-right">
|
|
<button class="btn btn-primary btn-lg" onclick="submitStep3()">
|
|
Continua
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ STEP 4: Il Tuo Profilo ═══ -->
|
|
<div class="wizard-step" id="step-3">
|
|
<h2 class="wizard-step-title">Completa il tuo profilo</h2>
|
|
<p class="wizard-step-subtitle">Inserisci le informazioni sul tuo ruolo in azienda.</p>
|
|
|
|
<div class="profile-form-wrapper">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="form-group">
|
|
<label class="form-label" for="full-name">Nome Completo</label>
|
|
<input type="text" id="full-name" class="form-input" placeholder="Mario Rossi">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="role">Ruolo in Azienda <span class="required">*</span></label>
|
|
<select id="role" class="form-select" required>
|
|
<option value="">-- Seleziona ruolo --</option>
|
|
<option value="ceo">CEO/Amministratore Delegato</option>
|
|
<option value="cto">CTO/Direttore Tecnico</option>
|
|
<option value="ciso">CISO/Responsabile Sicurezza</option>
|
|
<option value="dpo">DPO/Data Protection Officer</option>
|
|
<option value="compliance_manager">Compliance Manager</option>
|
|
<option value="it_manager">IT Manager</option>
|
|
<option value="legal">Responsabile Legale</option>
|
|
<option value="board_member">Membro CDA</option>
|
|
<option value="consultant">Consulente Esterno</option>
|
|
<option value="other">Altro</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group mb-0">
|
|
<label class="form-label" for="user-phone">Telefono</label>
|
|
<input type="text" id="user-phone" class="form-input" placeholder="+39 333 1234567">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="wizard-actions">
|
|
<button class="btn btn-secondary" onclick="goToStep(2)">
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd"/></svg>
|
|
Indietro
|
|
</button>
|
|
<div class="wizard-actions-right">
|
|
<button class="btn btn-primary btn-lg" onclick="submitStep4()">
|
|
Continua
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ═══ STEP 5: Classificazione NIS2 e Riepilogo ═══ -->
|
|
<div class="wizard-step" id="step-4">
|
|
<h2 class="wizard-step-title">Classificazione NIS2</h2>
|
|
<p class="wizard-step-subtitle">In base ai dati forniti, ecco la classificazione della tua organizzazione secondo la Direttiva NIS2.</p>
|
|
|
|
<!-- Classification Result -->
|
|
<div class="classification-result" id="classification-result">
|
|
<div class="classification-result-icon" id="classification-icon">
|
|
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 2.18l7 3.12v4.7c0 4.83-3.23 9.36-7 10.57-3.77-1.21-7-5.74-7-10.57V6.3l7-3.12z"/>
|
|
</svg>
|
|
</div>
|
|
<div class="classification-result-label" id="classification-label"></div>
|
|
<div class="classification-result-desc" id="classification-desc"></div>
|
|
</div>
|
|
|
|
<!-- Voluntary Compliance Option -->
|
|
<div class="voluntary-section" id="voluntary-section">
|
|
<div class="voluntary-card" id="voluntary-card">
|
|
<input type="checkbox" id="voluntary-checkbox" onchange="onVoluntaryChange(this.checked)">
|
|
<div>
|
|
<h4>Adesione Volontaria alla NIS2</h4>
|
|
<p>
|
|
Anche se la tua organizzazione non rientra nell'ambito di applicazione obbligatorio della
|
|
Direttiva NIS2, puoi scegliere di aderire volontariamente adottando le misure di sicurezza
|
|
previste dalla normativa. Questo consente di migliorare la postura di cybersicurezza e di
|
|
prepararsi a possibili future designazioni.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary -->
|
|
<div class="summary-card">
|
|
<div class="summary-card-header">Riepilogo Dati Aziendali</div>
|
|
<div class="summary-card-body">
|
|
<div class="summary-grid">
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Ragione Sociale</div>
|
|
<div class="summary-item-value" id="sum-company">-</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Partita IVA</div>
|
|
<div class="summary-item-value" id="sum-vat">-</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Settore</div>
|
|
<div class="summary-item-value" id="sum-sector">-</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Tipologia Soggetto</div>
|
|
<div class="summary-item-value" id="sum-entity-type">-</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Dipendenti</div>
|
|
<div class="summary-item-value" id="sum-employees">-</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<div class="summary-item-label">Fatturato Annuo</div>
|
|
<div class="summary-item-value" id="sum-turnover">-</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="wizard-actions">
|
|
<button class="btn btn-secondary" onclick="goToStep(3)">
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clip-rule="evenodd"/></svg>
|
|
Indietro
|
|
</button>
|
|
<div class="wizard-actions-right">
|
|
<button class="btn btn-primary btn-lg" id="complete-btn" onclick="completeOnboarding()">
|
|
<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
|
|
Completa e Vai alla Dashboard
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="js/api.js"></script>
|
|
<script src="js/common.js"></script>
|
|
<script>
|
|
// ── Auth check ──────────────────────────────────────────────────
|
|
if (!checkAuth()) throw new Error('Not authenticated');
|
|
|
|
// ── Extend API with onboarding methods ──────────────────────────
|
|
api.uploadVisura = async function(file) {
|
|
const formData = new FormData();
|
|
formData.append('visura', file);
|
|
const response = await fetch(this.baseUrl + '/onboarding/upload-visura', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.token,
|
|
'X-Organization-Id': this.orgId || ''
|
|
},
|
|
body: formData
|
|
});
|
|
return response.json();
|
|
};
|
|
api.fetchCompany = function(vatNumber) {
|
|
return this.post('/onboarding/fetch-company', { vat_number: vatNumber });
|
|
};
|
|
api.completeOnboarding = function(data) {
|
|
return this.post('/onboarding/complete', data);
|
|
};
|
|
|
|
// ── Wizard State ────────────────────────────────────────────────
|
|
const wizardState = {
|
|
currentStep: 1,
|
|
method: null, // 'visura' | 'certisource' | 'manual'
|
|
dataSource: null, // label for banner
|
|
visuraFile: null,
|
|
company: {
|
|
name: '',
|
|
vat_number: '',
|
|
fiscal_code: '',
|
|
address: '',
|
|
city: '',
|
|
website: '',
|
|
email: '',
|
|
phone: '',
|
|
sector: '',
|
|
employee_count: '',
|
|
annual_turnover: ''
|
|
},
|
|
profile: {
|
|
full_name: '',
|
|
role: '',
|
|
phone: ''
|
|
},
|
|
classification: null,
|
|
autoFilledFields: new Set(),
|
|
voluntaryCompliance: false
|
|
};
|
|
|
|
// ── Helper: parse employees range string to number ────────
|
|
function parseEmployeesRange(range) {
|
|
if (!range) return '';
|
|
if (typeof range === 'number') return range;
|
|
const str = String(range).trim();
|
|
if (str.endsWith('+')) return parseInt(str);
|
|
const parts = str.split('-');
|
|
if (parts.length === 2) return parseInt(parts[0]);
|
|
return parseInt(str) || '';
|
|
}
|
|
|
|
// ── Step 1: P.IVA Fetch ─────────────────────────────────────────
|
|
async function step1FetchCompany() {
|
|
const vat = document.getElementById('s1-vat').value.trim();
|
|
if (!vat || vat.length !== 11) {
|
|
showNotification('Inserisci una Partita IVA valida (11 cifre numeriche).', 'warning');
|
|
return;
|
|
}
|
|
|
|
const btn = document.getElementById('s1-fetch-btn');
|
|
const loading = document.getElementById('s1-loading');
|
|
const resultDiv = document.getElementById('s1-result');
|
|
|
|
btn.disabled = true;
|
|
loading.classList.add('active');
|
|
resultDiv.style.display = 'none';
|
|
|
|
try {
|
|
const result = await api.fetchCompany(vat);
|
|
|
|
if (result.success && result.data) {
|
|
const d = result.data;
|
|
wizardState.company.name = d.company_name || d.ragione_sociale || d.name || '';
|
|
wizardState.company.vat_number = vat;
|
|
wizardState.company.fiscal_code = d.fiscal_code || d.codice_fiscale || '';
|
|
wizardState.company.address = d.address || d.indirizzo || '';
|
|
wizardState.company.city = d.city || d.citta || '';
|
|
wizardState.company.website = d.website || d.sito_web || '';
|
|
wizardState.company.email = d.email || d.pec || '';
|
|
wizardState.company.phone = d.phone || d.telefono || '';
|
|
wizardState.company.sector = d.suggested_sector || d.sector || '';
|
|
wizardState.company.employee_count = parseEmployeesRange(d.employees_range) || d.employee_count || d.employees || '';
|
|
wizardState.company.annual_turnover = '';
|
|
wizardState.dataSource = 'Dati precompilati da CertiSource';
|
|
|
|
wizardState.autoFilledFields.clear();
|
|
if (wizardState.company.name) wizardState.autoFilledFields.add('company-name');
|
|
if (wizardState.company.vat_number) wizardState.autoFilledFields.add('vat-number');
|
|
if (wizardState.company.fiscal_code) wizardState.autoFilledFields.add('fiscal-code');
|
|
if (wizardState.company.address) wizardState.autoFilledFields.add('address');
|
|
if (wizardState.company.city) wizardState.autoFilledFields.add('city');
|
|
if (wizardState.company.email) wizardState.autoFilledFields.add('company-email');
|
|
if (wizardState.company.phone) wizardState.autoFilledFields.add('company-phone');
|
|
if (wizardState.company.sector) wizardState.autoFilledFields.add('sector');
|
|
if (wizardState.company.employee_count) wizardState.autoFilledFields.add('employee-count');
|
|
|
|
resultDiv.style.cssText = 'display:block; padding:.75rem; border-radius:8px; background:var(--success-bg); color:var(--secondary);';
|
|
resultDiv.innerHTML = '<strong>✓ ' + (wizardState.company.name || 'Azienda trovata') + '</strong><br><small>' + (d.address || d.city || '') + '</small>';
|
|
document.getElementById('s1-continue-btn').style.display = 'inline-flex';
|
|
showNotification('Azienda trovata: ' + (wizardState.company.name || vat), 'success');
|
|
} else {
|
|
resultDiv.style.cssText = 'display:block; padding:.75rem; border-radius:8px; background:var(--warning-bg,#fff3cd); color:#856404;';
|
|
resultDiv.textContent = 'Azienda non trovata. Puoi inserire i dati manualmente.';
|
|
step1ManualEntry(vat);
|
|
}
|
|
} catch (err) {
|
|
showNotification('Errore di connessione al server.', 'error');
|
|
} finally {
|
|
btn.disabled = false;
|
|
loading.classList.remove('active');
|
|
}
|
|
}
|
|
|
|
function step1ManualEntry(vat) {
|
|
wizardState.company.vat_number = vat || document.getElementById('s1-vat').value.trim();
|
|
wizardState.dataSource = null;
|
|
wizardState.autoFilledFields.clear();
|
|
document.getElementById('s1-continue-btn').style.display = 'inline-flex';
|
|
showNotification('Inserisci i dati aziendali manualmente.', 'info');
|
|
}
|
|
|
|
// ── Step navigation ─────────────────────────────────────────────
|
|
function goToStep(step) {
|
|
wizardState.currentStep = step;
|
|
|
|
// Hide all steps
|
|
document.querySelectorAll('.wizard-step').forEach(s => s.classList.remove('active'));
|
|
|
|
// Show target step
|
|
const targetStep = document.getElementById('step-' + step);
|
|
if (targetStep) targetStep.classList.add('active');
|
|
|
|
// Step 2: populate company form from wizard state
|
|
if (step === 2) {
|
|
populateCompanyForm();
|
|
}
|
|
|
|
// Step 3: load user profile
|
|
if (step === 3) {
|
|
loadUserProfile();
|
|
}
|
|
|
|
// Step 4: run classification and populate summary
|
|
if (step === 4) {
|
|
runClassificationAndSummary();
|
|
}
|
|
|
|
// Update stepper
|
|
updateStepper(step);
|
|
|
|
// Scroll to top
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
|
|
function updateStepper(currentStep) {
|
|
document.querySelectorAll('.stepper-step').forEach(el => {
|
|
const s = parseInt(el.dataset.step);
|
|
el.classList.remove('active', 'completed');
|
|
const numEl = el.querySelector('.stepper-number');
|
|
|
|
if (s < currentStep) {
|
|
el.classList.add('completed');
|
|
numEl.innerHTML = '<svg width="16" height="16" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>';
|
|
} else if (s === currentStep) {
|
|
el.classList.add('active');
|
|
numEl.textContent = s;
|
|
} else {
|
|
numEl.textContent = s;
|
|
}
|
|
});
|
|
|
|
// Update connectors
|
|
document.querySelectorAll('.stepper-connector').forEach(el => {
|
|
const afterStep = parseInt(el.dataset.after);
|
|
el.classList.toggle('completed', afterStep < currentStep);
|
|
});
|
|
}
|
|
|
|
// ── Step 2a: Visura Upload (legacy, kept for API completeness) ──
|
|
|
|
function handleVisuraFile(file) {
|
|
// Validate type
|
|
if (file.type !== 'application/pdf') {
|
|
showNotification('Il file deve essere in formato PDF.', 'warning');
|
|
return;
|
|
}
|
|
|
|
// Validate size (10 MB)
|
|
if (file.size > 10 * 1024 * 1024) {
|
|
showNotification('Il file non deve superare i 10 MB.', 'warning');
|
|
return;
|
|
}
|
|
|
|
wizardState.visuraFile = file;
|
|
uploadArea.classList.add('has-file');
|
|
document.getElementById('upload-file-name').textContent = file.name;
|
|
document.getElementById('analyze-visura-btn').disabled = false;
|
|
}
|
|
|
|
async function analyzeVisura() {
|
|
if (!wizardState.visuraFile) return;
|
|
|
|
const btn = document.getElementById('analyze-visura-btn');
|
|
const loading = document.getElementById('visura-loading');
|
|
const btnArea = document.getElementById('visura-upload-btn-area');
|
|
|
|
btn.disabled = true;
|
|
btnArea.style.display = 'none';
|
|
loading.classList.add('active');
|
|
|
|
try {
|
|
const result = await api.uploadVisura(wizardState.visuraFile);
|
|
|
|
if (result.success && result.data) {
|
|
// Map extracted data to wizard state
|
|
const d = result.data;
|
|
wizardState.company.name = d.company_name || d.ragione_sociale || d.name || '';
|
|
wizardState.company.vat_number = d.vat_number || d.partita_iva || '';
|
|
wizardState.company.fiscal_code = d.fiscal_code || d.codice_fiscale || '';
|
|
wizardState.company.address = d.address || d.indirizzo || '';
|
|
wizardState.company.city = d.city || d.citta || '';
|
|
wizardState.company.website = d.website || d.sito_web || '';
|
|
wizardState.company.email = d.email || d.pec || '';
|
|
wizardState.company.phone = d.phone || d.telefono || '';
|
|
wizardState.company.sector = d.suggested_sector || d.sector || '';
|
|
wizardState.company.employee_count = parseEmployeesRange(d.employees_range) || d.employee_count || d.employees || '';
|
|
// Fatturato resta SEMPRE manuale — non auto-compilare dalla visura
|
|
wizardState.company.annual_turnover = '';
|
|
wizardState.dataSource = 'Dati precompilati dalla visura camerale';
|
|
|
|
// Track auto-filled fields
|
|
wizardState.autoFilledFields.clear();
|
|
if (wizardState.company.name) wizardState.autoFilledFields.add('company-name');
|
|
if (wizardState.company.vat_number) wizardState.autoFilledFields.add('vat-number');
|
|
if (wizardState.company.fiscal_code) wizardState.autoFilledFields.add('fiscal-code');
|
|
if (wizardState.company.address) wizardState.autoFilledFields.add('address');
|
|
if (wizardState.company.city) wizardState.autoFilledFields.add('city');
|
|
if (wizardState.company.email) wizardState.autoFilledFields.add('company-email');
|
|
if (wizardState.company.phone) wizardState.autoFilledFields.add('company-phone');
|
|
if (wizardState.company.sector) wizardState.autoFilledFields.add('sector');
|
|
if (wizardState.company.employee_count) wizardState.autoFilledFields.add('employee-count');
|
|
|
|
showNotification('Visura analizzata con successo!', 'success');
|
|
|
|
// Auto-advance to step 3
|
|
setTimeout(() => goToStep(3), 600);
|
|
} else {
|
|
showNotification(result.message || 'Errore nell\'analisi della visura.', 'error');
|
|
btnArea.style.display = 'block';
|
|
btn.disabled = false;
|
|
}
|
|
} catch (err) {
|
|
showNotification('Errore di connessione al server.', 'error');
|
|
btnArea.style.display = 'block';
|
|
btn.disabled = false;
|
|
} finally {
|
|
loading.classList.remove('active');
|
|
}
|
|
}
|
|
|
|
// ── Step 2b: CertiSource ────────────────────────────────────────
|
|
async function fetchCompany() {
|
|
const vatInput = document.getElementById('cs-vat');
|
|
const vat = vatInput.value.trim();
|
|
|
|
if (!vat) {
|
|
showNotification('Inserisci la Partita IVA.', 'warning');
|
|
return;
|
|
}
|
|
|
|
const btn = document.getElementById('fetch-company-btn');
|
|
const loading = document.getElementById('certisource-loading');
|
|
|
|
btn.disabled = true;
|
|
btn.innerHTML = '<div class="spinner" style="width:18px;height:18px;border-width:2px;margin:0;"></div> Ricerca...';
|
|
loading.classList.add('active');
|
|
|
|
try {
|
|
const result = await api.fetchCompany(vat);
|
|
|
|
if (result.success && result.data) {
|
|
const d = result.data;
|
|
wizardState.company.name = d.company_name || d.ragione_sociale || d.name || '';
|
|
wizardState.company.vat_number = d.vat_number || d.partita_iva || vat;
|
|
wizardState.company.fiscal_code = d.fiscal_code || d.codice_fiscale || '';
|
|
wizardState.company.address = d.address || d.indirizzo || '';
|
|
wizardState.company.city = d.city || d.citta || '';
|
|
wizardState.company.website = d.website || d.sito_web || '';
|
|
wizardState.company.email = d.email || d.pec || '';
|
|
wizardState.company.phone = d.phone || d.telefono || '';
|
|
wizardState.company.sector = d.suggested_sector || d.sector || '';
|
|
wizardState.company.employee_count = parseEmployeesRange(d.employees_range) || d.employee_count || d.employees || '';
|
|
// Fatturato resta SEMPRE manuale
|
|
wizardState.company.annual_turnover = '';
|
|
wizardState.dataSource = 'Dati recuperati da CertiSource';
|
|
|
|
// Track auto-filled fields
|
|
wizardState.autoFilledFields.clear();
|
|
if (wizardState.company.name) wizardState.autoFilledFields.add('company-name');
|
|
if (wizardState.company.vat_number) wizardState.autoFilledFields.add('vat-number');
|
|
if (wizardState.company.fiscal_code) wizardState.autoFilledFields.add('fiscal-code');
|
|
if (wizardState.company.address) wizardState.autoFilledFields.add('address');
|
|
if (wizardState.company.city) wizardState.autoFilledFields.add('city');
|
|
if (wizardState.company.email) wizardState.autoFilledFields.add('company-email');
|
|
if (wizardState.company.phone) wizardState.autoFilledFields.add('company-phone');
|
|
if (wizardState.company.sector) wizardState.autoFilledFields.add('sector');
|
|
if (wizardState.company.employee_count) wizardState.autoFilledFields.add('employee-count');
|
|
|
|
showNotification('Dati aziendali recuperati con successo!', 'success');
|
|
|
|
// Auto-advance to step 3
|
|
setTimeout(() => goToStep(2), 600);
|
|
} else {
|
|
showNotification(result.message || 'Impossibile recuperare i dati. Verifica la Partita IVA.', 'error');
|
|
}
|
|
} catch (err) {
|
|
showNotification('Errore di connessione al server.', 'error');
|
|
} finally {
|
|
loading.classList.remove('active');
|
|
btn.disabled = false;
|
|
btn.innerHTML = '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/></svg> Recupera Dati';
|
|
}
|
|
}
|
|
|
|
// ── Step 3: Company Form ────────────────────────────────────────
|
|
function populateCompanyForm() {
|
|
const c = wizardState.company;
|
|
document.getElementById('company-name').value = c.name || '';
|
|
document.getElementById('vat-number').value = c.vat_number || '';
|
|
document.getElementById('fiscal-code').value = c.fiscal_code || '';
|
|
document.getElementById('address').value = c.address || '';
|
|
document.getElementById('city').value = c.city || '';
|
|
document.getElementById('website').value = c.website || '';
|
|
document.getElementById('company-email').value = c.email || '';
|
|
document.getElementById('company-phone').value = c.phone || '';
|
|
document.getElementById('employee-count').value = c.employee_count || '';
|
|
document.getElementById('annual-turnover').value = c.annual_turnover || '';
|
|
|
|
// Set sector if available
|
|
if (c.sector) {
|
|
const sectorSelect = document.getElementById('sector');
|
|
if (sectorSelect.querySelector('option[value="' + c.sector + '"]')) {
|
|
sectorSelect.value = c.sector;
|
|
}
|
|
}
|
|
|
|
// Show data source banner
|
|
const banner = document.getElementById('data-source-banner');
|
|
const bannerText = document.getElementById('data-source-text');
|
|
if (wizardState.dataSource) {
|
|
bannerText.textContent = wizardState.dataSource;
|
|
banner.classList.add('visible');
|
|
} else {
|
|
banner.classList.remove('visible');
|
|
}
|
|
|
|
// Apply auto-fill visual indicators
|
|
const autoFields = wizardState.autoFilledFields;
|
|
document.querySelectorAll('#step-2 .form-input, #step-2 .form-select').forEach(el => {
|
|
const wrapper = el.closest('.form-group');
|
|
if (!wrapper) return;
|
|
|
|
// Remove previous indicators
|
|
wrapper.classList.remove('auto-filled');
|
|
const existing = wrapper.querySelector('.auto-fill-badge');
|
|
if (existing) existing.remove();
|
|
|
|
if (autoFields.has(el.id)) {
|
|
wrapper.classList.add('auto-filled');
|
|
const badge = document.createElement('span');
|
|
badge.className = 'auto-fill-badge';
|
|
badge.textContent = wizardState.dataSource ? 'auto-compilato' : 'da visura';
|
|
const label = wrapper.querySelector('.form-label');
|
|
if (label) label.appendChild(badge);
|
|
}
|
|
});
|
|
}
|
|
|
|
function submitStep3() {
|
|
// Read form values into state
|
|
const name = document.getElementById('company-name').value.trim();
|
|
const sector = document.getElementById('sector').value;
|
|
const employees = document.getElementById('employee-count').value;
|
|
const turnover = document.getElementById('annual-turnover').value;
|
|
|
|
// Validate required fields
|
|
if (!name) {
|
|
showNotification('Inserisci la ragione sociale.', 'warning');
|
|
document.getElementById('company-name').focus();
|
|
return;
|
|
}
|
|
if (!sector) {
|
|
showNotification('Seleziona un settore NIS2.', 'warning');
|
|
document.getElementById('sector').focus();
|
|
return;
|
|
}
|
|
if (!employees || parseInt(employees) <= 0) {
|
|
showNotification('Inserisci il numero di dipendenti.', 'warning');
|
|
document.getElementById('employee-count').focus();
|
|
return;
|
|
}
|
|
if (!turnover || parseInt(turnover) < 0) {
|
|
showNotification('Inserisci il fatturato annuo.', 'warning');
|
|
document.getElementById('annual-turnover').focus();
|
|
return;
|
|
}
|
|
|
|
// Save all values to state
|
|
wizardState.company.name = name;
|
|
wizardState.company.vat_number = document.getElementById('vat-number').value.trim();
|
|
wizardState.company.fiscal_code = document.getElementById('fiscal-code').value.trim();
|
|
wizardState.company.address = document.getElementById('address').value.trim();
|
|
wizardState.company.city = document.getElementById('city').value.trim();
|
|
wizardState.company.website = document.getElementById('website').value.trim();
|
|
wizardState.company.email = document.getElementById('company-email').value.trim();
|
|
wizardState.company.phone = document.getElementById('company-phone').value.trim();
|
|
wizardState.company.sector = sector;
|
|
wizardState.company.employee_count = parseInt(employees);
|
|
wizardState.company.annual_turnover = parseInt(turnover);
|
|
|
|
goToStep(3);
|
|
}
|
|
|
|
// ── Step 4: User Profile ────────────────────────────────────────
|
|
async function loadUserProfile() {
|
|
try {
|
|
const result = await api.getMe();
|
|
if (result.success && result.data) {
|
|
const nameInput = document.getElementById('full-name');
|
|
if (!nameInput.value && result.data.full_name) {
|
|
nameInput.value = result.data.full_name;
|
|
wizardState.profile.full_name = result.data.full_name;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Silently ignore
|
|
}
|
|
}
|
|
|
|
function submitStep4() {
|
|
const role = document.getElementById('role').value;
|
|
|
|
if (!role) {
|
|
showNotification('Seleziona il tuo ruolo in azienda.', 'warning');
|
|
document.getElementById('role').focus();
|
|
return;
|
|
}
|
|
|
|
wizardState.profile.full_name = document.getElementById('full-name').value.trim();
|
|
wizardState.profile.role = role;
|
|
wizardState.profile.phone = document.getElementById('user-phone').value.trim();
|
|
|
|
goToStep(4);
|
|
}
|
|
|
|
// ── Step 5: Classification & Summary ────────────────────────────
|
|
|
|
// NIS2 Classification Logic (from setup-org.html)
|
|
function classifyLocally(sector, employees, turnover) {
|
|
const annexI = [
|
|
'energy_electricity', 'energy_district_heating', 'energy_oil', 'energy_gas',
|
|
'energy_hydrogen', 'transport_air', 'transport_rail', 'transport_water',
|
|
'transport_road', 'banking', 'financial_markets', 'health', 'drinking_water',
|
|
'waste_water', 'digital_infrastructure', 'ict_service_management',
|
|
'public_administration', 'space'
|
|
];
|
|
|
|
const annexII = [
|
|
'postal_courier', 'waste_management', 'chemicals', 'food',
|
|
'manufacturing_medical', 'manufacturing_computers', 'manufacturing_electrical',
|
|
'manufacturing_machinery', 'manufacturing_vehicles', 'manufacturing_transport',
|
|
'digital_providers', 'research'
|
|
];
|
|
|
|
const isAnnexI = annexI.includes(sector);
|
|
const isAnnexII = annexII.includes(sector);
|
|
const isLarge = employees >= 250 || turnover >= 50000000;
|
|
const isMedium = employees >= 50 || turnover >= 10000000;
|
|
|
|
if (isAnnexI && isLarge) {
|
|
return {
|
|
classification: 'essential',
|
|
label: 'Soggetto Essenziale',
|
|
description: 'La vostra organizzazione rientra tra i soggetti essenziali ai sensi della Direttiva NIS2, in quanto opera in un settore ad alta criticita\' (Allegato I) e supera le soglie dimensionali per la classificazione come grande impresa. Siete tenuti al rispetto completo degli obblighi di sicurezza con vigilanza ex ante.'
|
|
};
|
|
} else if ((isAnnexI || isAnnexII) && isMedium) {
|
|
return {
|
|
classification: 'important',
|
|
label: 'Soggetto Importante',
|
|
description: 'La vostra organizzazione rientra tra i soggetti importanti ai sensi della Direttiva NIS2. Siete tenuti a rispettare gli obblighi di sicurezza e di notifica degli incidenti, con un regime di vigilanza ex post.'
|
|
};
|
|
} else if (sector === 'other' || (!isAnnexI && !isAnnexII)) {
|
|
return {
|
|
classification: 'not_applicable',
|
|
label: 'Non Applicabile',
|
|
description: 'In base ai dati forniti, la vostra organizzazione non sembra rientrare nell\'ambito di applicazione della Direttiva NIS2. Consigliamo comunque di adottare misure di cybersicurezza adeguate e di verificare con le autorita\' competenti.'
|
|
};
|
|
} else {
|
|
return {
|
|
classification: 'not_applicable',
|
|
label: 'Sotto le Soglie',
|
|
description: 'La vostra organizzazione opera in un settore coperto dalla NIS2 ma non raggiunge le soglie dimensionali minime (50 dipendenti o 10M EUR di fatturato). Potreste comunque essere designati dalle autorita\' nazionali.'
|
|
};
|
|
}
|
|
}
|
|
|
|
function runClassificationAndSummary() {
|
|
const c = wizardState.company;
|
|
const sector = c.sector;
|
|
const employees = parseInt(c.employee_count) || 0;
|
|
const turnover = parseInt(c.annual_turnover) || 0;
|
|
|
|
// Run classification
|
|
const result = classifyLocally(sector, employees, turnover);
|
|
wizardState.classification = result;
|
|
|
|
// Reset voluntary state when re-entering step 5
|
|
wizardState.voluntaryCompliance = false;
|
|
const voluntaryCheckbox = document.getElementById('voluntary-checkbox');
|
|
if (voluntaryCheckbox) voluntaryCheckbox.checked = false;
|
|
const voluntaryCard = document.getElementById('voluntary-card');
|
|
if (voluntaryCard) voluntaryCard.classList.remove('checked');
|
|
|
|
// Show/hide voluntary compliance section
|
|
const voluntarySection = document.getElementById('voluntary-section');
|
|
if (result.classification === 'not_applicable') {
|
|
voluntarySection.classList.add('visible');
|
|
} else {
|
|
voluntarySection.classList.remove('visible');
|
|
}
|
|
|
|
// Update classification UI
|
|
const container = document.getElementById('classification-result');
|
|
const labelEl = document.getElementById('classification-label');
|
|
const descEl = document.getElementById('classification-desc');
|
|
const iconEl = document.getElementById('classification-icon');
|
|
|
|
container.className = 'classification-result';
|
|
|
|
if (result.classification === 'essential') {
|
|
container.classList.add('essential');
|
|
iconEl.innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 2.18l7 3.12v4.7c0 4.83-3.23 9.36-7 10.57-3.77-1.21-7-5.74-7-10.57V6.3l7-3.12z"/><path d="M10 12.5l-2-2-1.41 1.41L10 15.32l5.41-5.41L14 8.5l-4 4z"/></svg>';
|
|
} else if (result.classification === 'important') {
|
|
container.classList.add('important');
|
|
iconEl.innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 2.18l7 3.12v4.7c0 4.83-3.23 9.36-7 10.57-3.77-1.21-7-5.74-7-10.57V6.3l7-3.12z"/></svg>';
|
|
} else {
|
|
container.classList.add('not-applicable');
|
|
iconEl.innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
|
}
|
|
|
|
labelEl.textContent = result.label;
|
|
descEl.textContent = result.description;
|
|
|
|
// Get the display text for the sector
|
|
const sectorSelect = document.getElementById('sector');
|
|
const sectorOption = sectorSelect.querySelector('option[value="' + c.sector + '"]');
|
|
const sectorText = sectorOption ? sectorOption.textContent : c.sector;
|
|
|
|
// Populate summary
|
|
document.getElementById('sum-company').textContent = c.name || '-';
|
|
document.getElementById('sum-vat').textContent = c.vat_number || '-';
|
|
document.getElementById('sum-sector').textContent = sectorText || '-';
|
|
document.getElementById('sum-entity-type').textContent = result.label || '-';
|
|
document.getElementById('sum-employees').textContent = employees ? employees.toLocaleString('it-IT') : '-';
|
|
document.getElementById('sum-turnover').textContent = turnover ? '\u20AC ' + turnover.toLocaleString('it-IT') : '-';
|
|
}
|
|
|
|
// ── Voluntary Compliance Toggle ───────────────────────────────
|
|
function onVoluntaryChange(checked) {
|
|
wizardState.voluntaryCompliance = checked;
|
|
|
|
const card = document.getElementById('voluntary-card');
|
|
const container = document.getElementById('classification-result');
|
|
const labelEl = document.getElementById('classification-label');
|
|
const sumEntityType = document.getElementById('sum-entity-type');
|
|
|
|
card.classList.toggle('checked', checked);
|
|
|
|
if (checked) {
|
|
container.className = 'classification-result voluntary';
|
|
container.querySelector('.classification-result-icon').innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 2.18l7 3.12v4.7c0 4.83-3.23 9.36-7 10.57-3.77-1.21-7-5.74-7-10.57V6.3l7-3.12z"/><path d="M10 12.5l-2-2-1.41 1.41L10 15.32l5.41-5.41L14 8.5l-4 4z"/></svg>';
|
|
labelEl.textContent = 'Adesione Volontaria';
|
|
document.getElementById('classification-desc').textContent = 'La tua organizzazione aderisce volontariamente alla Direttiva NIS2, adottando le misure di sicurezza previste dalla normativa per migliorare la propria postura di cybersicurezza.';
|
|
sumEntityType.textContent = 'Adesione Volontaria';
|
|
} else {
|
|
container.className = 'classification-result not-applicable';
|
|
container.querySelector('.classification-result-icon').innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>';
|
|
labelEl.textContent = wizardState.classification.label;
|
|
document.getElementById('classification-desc').textContent = wizardState.classification.description;
|
|
sumEntityType.textContent = wizardState.classification.label;
|
|
}
|
|
}
|
|
|
|
// ── Complete Onboarding ─────────────────────────────────────────
|
|
async function completeOnboarding() {
|
|
const btn = document.getElementById('complete-btn');
|
|
btn.disabled = true;
|
|
btn.innerHTML = '<div class="spinner" style="width:18px;height:18px;border-width:2px;margin:0;"></div> Completamento in corso...';
|
|
|
|
const c = wizardState.company;
|
|
const p = wizardState.profile;
|
|
const cl = wizardState.classification;
|
|
|
|
const payload = {
|
|
// Company data (field names match backend OnboardingController)
|
|
name: c.name,
|
|
vat_number: c.vat_number,
|
|
fiscal_code: c.fiscal_code,
|
|
address: c.address,
|
|
city: c.city,
|
|
website: c.website,
|
|
contact_email: c.email,
|
|
contact_phone: c.phone,
|
|
sector: c.sector,
|
|
employee_count: parseInt(c.employee_count) || 0,
|
|
annual_turnover_eur: parseInt(c.annual_turnover) || 0,
|
|
// Voluntary compliance
|
|
voluntary_compliance: wizardState.voluntaryCompliance ? 1 : 0,
|
|
// Profile data
|
|
full_name: p.full_name,
|
|
phone: p.phone,
|
|
// Country
|
|
country: 'IT',
|
|
};
|
|
|
|
try {
|
|
const result = await api.completeOnboarding(payload);
|
|
|
|
if (result.success && result.data) {
|
|
const orgId = result.data.id || result.data.organization_id;
|
|
if (orgId) {
|
|
api.setOrganization(orgId);
|
|
}
|
|
|
|
showNotification('Configurazione completata con successo!', 'success');
|
|
|
|
setTimeout(() => {
|
|
const dest = api.isConsultant() ? 'companies.html' : 'dashboard.html';
|
|
window.location.href = dest;
|
|
}, 1000);
|
|
} else {
|
|
showNotification(result.message || 'Errore nel completamento.', 'error');
|
|
btn.disabled = false;
|
|
btn.innerHTML = '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg> Completa e Vai alla Dashboard';
|
|
}
|
|
} catch (err) {
|
|
showNotification('Errore di connessione al server.', 'error');
|
|
btn.disabled = false;
|
|
btn.innerHTML = '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg> Completa e Vai alla Dashboard';
|
|
}
|
|
}
|
|
|
|
// ── Allow P.IVA input to submit with Enter ───────────────────────
|
|
document.getElementById('s1-vat').addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
step1FetchCompany();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|