// EvaluationCMMI.jsx — Verigo Global: CMMC 2.0 online readiness evaluation (level-driven, gated, resumable)
const { V: EV, MAXW: EMW, FONT: EFT } = window;
/* ── PROGRESS PERSISTENCE (localStorage) ─────────────────── */
const PROG_KEY = 'verigo_cmmi_eval';
const loadProg = () => { try { return JSON.parse(localStorage.getItem(PROG_KEY) || 'null'); } catch (e) { return null; } };
const saveProg = (p) => { try { localStorage.setItem(PROG_KEY, JSON.stringify(p)); } catch (e) {} };
const clearProg = () => { try { localStorage.removeItem(PROG_KEY); } catch (e) {} };
const cPreviewThemes = [
['trending', 'EST · Estimating', 62],
['clipboard', 'PLAN · Planning', 74],
['cpu', 'TS · Technical Solution', 48],
['refresh', 'CAR · Causal Analysis', 55],
];
/* ── RESUME BANNER ───────────────────────────────────────── */
const MiResumeBanner = ({ prog, onResume, onStartOver }) => {
const done = prog.stage === 'results';
const when = prog.ts ? new Date(prog.ts).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) + ' · ' + new Date(prog.ts).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }) : '';
const lvl = prog.level ? 'Level ' + prog.level : '';
return (
{done ? 'Your last evaluation is complete and saved.' : 'You have an evaluation in progress.'}
{prog.scope && prog.scope.company ? prog.scope.company + ' · ' : ''}{lvl ? lvl + ' · ' : ''}{when ? 'Saved ' + when : 'Pick up where you left off.'}
{done ? 'View saved results' : 'Resume evaluation'}
Start over
);
};
/* ── PREVIEW DASHBOARD (illustrative, intro only) ────────── */
const MiScorePreview = () => (
Readiness report
Sample · L2
Overall maturity
Established
41 of 110 practices need work before assessment.
{cPreviewThemes.map(([ic, name, pct], i) => (
))}
);
/* ── INTRO STAGE ─────────────────────────────────────────── */
const MiEvalIntro = ({ onStart, onNav, resume, onResume, onStartOver }) => {
const steps = [
['target', 'Pick your level & scope', 'Choose Level 1, 2, or 3 and tell us about your environment — your level decides exactly which practices the evaluation asks about.'],
['gauge', 'Instant scoring', 'Get a weighted maturity score with a domain-by-domain breakdown showing where you stand against 800-171.'],
['flag', 'Mapped action plan', 'Every gap links straight to the toolkit document, policy, or practice that closes it — so you know the next move.'],
];
return (
{resume &&
}
onNav('toolkit:cmmi')} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#7A7A8A', fontSize: 13, fontWeight: 600, padding: 0, fontFamily: EFT }}>CMMI Toolkit
/
Online Evaluation
Level-aware · ~12 minutes · free
Know where you stand on CMMI v2.0.
Measure your current state against the NIST SP 800-171 practices for the CMMC level you’re targeting. Pick your level in scope and the evaluation asks only the practices that apply — then maps every gap to the toolkit documents that close it.
{resume ? 'Start a new evaluation' : 'Start the evaluation'}
onNav('contact')}>Talk to a practitioner
Free and confidential. We'll ask for a few details so we can send your results.
{steps.map(([ic, t, d], i) => (
{String(i + 1).padStart(2, '0')}
{t}
{d}
))}
{resume ? 'Start a new evaluation' : 'Start the evaluation'}
);
};
/* ── SCOPE FORM ──────────────────────────────────────────── */
const SCOPE_FIELDS_CMMC = {
industry: ['Defense / aerospace', 'IT / managed services', 'Manufacturing', 'Software / SaaS', 'Professional services', 'Logistics', 'Other'],
employees: ['1–50', '51–200', '201–1,000', '1,000+'],
region: ['United States', 'Other'],
locations: ['1 site', '2–5 sites', '6–20 sites', '20+ sites'],
target: ['Within 3 months', 'Within 6 months', '6–12 months', '12+ months', 'Just exploring'],
};
// CMMC levels — the choice here decides which domains/questions the evaluation asks.
const LEVEL_OPTIONS = [
['ml2', 'ML2 — Managed', '10 practice areas', 'Formal project management, planning, monitoring, and QA.'],
['ml3', 'ML3 — Defined', '20 practice areas', 'Organization-wide standard processes — the most common target.'],
['ml45', 'ML4/5 — Quantitative', '20 practice areas', 'Statistical process control and continuous optimization.'],
];
const evInput = { fontFamily: EFT, fontSize: 14, color: EV.black, background: '#fff', border: `1.5px solid ${EV.g200}`, borderRadius: 8, padding: '11px 14px', outline: 'none', width: '100%' };
const evLabel = { fontSize: 12.5, fontWeight: 600, color: EV.black, display: 'block', marginBottom: 7 };
const evSelect = { ...evInput, appearance: 'none', backgroundImage: "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239A9AAA' stroke-width='2.5'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\")", backgroundRepeat: 'no-repeat', backgroundPosition: 'right 12px center', paddingRight: 32, cursor: 'pointer' };
const MiScopeForm = ({ onSubmit, onBack, saved }) => {
const u = (() => { try { return window.TK_CMMI.getUser() || {}; } catch (e) { return {}; } })();
const sv = saved || {};
const [f, setF] = React.useState({
company: sv.company || u.company || '', name: sv.name || u.name || '', email: sv.email || u.email || '', phone: sv.phone || u.phone || '', role: sv.role || u.role || '',
industry: sv.industry || u.industry || SCOPE_FIELDS_CMMC.industry[0], employees: sv.employees || u.employees || SCOPE_FIELDS_CMMC.employees[0],
region: sv.region || u.region || SCOPE_FIELDS_CMMC.region[0], locations: sv.locations || u.locations || SCOPE_FIELDS_CMMC.locations[0],
systems: sv.systems || u.systems || '', certs: sv.certs || u.certs || '', target: sv.target || u.target || SCOPE_FIELDS_CMMC.target[1],
});
const [level, setLevel] = React.useState(() => (saved && saved.level) ? Number(saved.level) : 2);
const set = (k, v) => setF((p) => ({ ...p, [k]: v }));
const text = (k, lbl, props = {}) => {lbl} set(k, e.target.value)} {...props} />
;
const sel = (k, lbl) => {lbl} set(k, e.target.value)}>{SCOPE_FIELDS_CMMC[k].map((o) => {o} )}
;
const lvlMeta = LEVEL_OPTIONS.find((o) => o[0] === level);
return (
Step 1 of 2 · Scope your assessment
Tell us about your organization
Pick your target CMMC level and a few details. Your level sets which practices we assess; the rest lets us tailor your results and quote.
);
};
/* ── PAGE ────────────────────────────────────────────────── */
const EvaluationCMMIPage = ({ onNav }) => {
const [stage, setStage] = React.useState('intro'); // intro | scope | quiz | results
const [gate, setGate] = React.useState(false);
const [results, setResults] = React.useState(null);
const [user, setUser] = React.useState(null);
const [scopeData, setScopeData] = React.useState(null); // { form, level }
const [resume, setResume] = React.useState(null);
const [seed, setSeed] = React.useState(null);
React.useEffect(() => {
try { setUser(window.TK_CMMI.getUser()); } catch (e) {}
const p = loadProg();
if (p && p.stage && p.stage !== 'intro') setResume(p);
}, []);
const persist = (patch) => { const base = loadProg() || {}; saveProg({ ...base, ...patch, ts: Date.now() }); };
const contactOk = () => { try { return !!sessionStorage.getItem('verigo_contact_ok'); } catch (e) { return false; } };
const requestStart = () => {
if (contactOk()) { setUser(window.TK_CMMI.getUser()); setStage('scope'); window.scrollTo({ top: 0 }); }
else { setGate(true); }
};
const onGateSubmit = (form) => {
window.TK_CMMI.storeLead({ ...form, source: 'evaluation' });
try { sessionStorage.setItem('verigo_contact_ok', '1'); } catch (e) {}
setUser(window.TK_CMMI.getUser());
setGate(false);
setStage('scope');
window.scrollTo({ top: 0 });
};
const onScopeSubmit = (form) => {
const ml = form.level || 'ml3';
window.TK_CMMI.storeLead({ ...form, level: 'Level ' + ml, source: 'evaluation-scope' });
setUser(window.TK_CMMI.getUser());
setScopeData({ form, level: ml });
setSeed({ answers: {}, step: 0 });
saveProg({ stage: 'quiz', scope: form, level: ml, answers: {}, step: 0, ts: Date.now() });
setStage('quiz');
window.scrollTo({ top: 0 });
};
const onQuizProgress = (answers, step) => { persist({ stage: 'quiz', answers, step }); };
const onComplete = (res) => { setResults(res); persist({ stage: 'results', results: res }); setStage('results'); window.scrollTo({ top: 0 }); };
const retake = () => { setResults(null); setSeed({ answers: {}, step: 0 }); persist({ stage: 'quiz', answers: {}, step: 0, results: null }); setStage('quiz'); window.scrollTo({ top: 0 }); };
const doResume = () => {
const p = resume; if (!p) return;
if (p.scope) setScopeData({ form: p.scope, level: Number(p.level) || 2 });
setSeed({ answers: p.answers || {}, step: p.step || 0 });
if (p.results) setResults(p.results);
setResume(null);
setStage(p.stage === 'results' ? 'results' : 'quiz');
window.scrollTo({ top: 0 });
};
const doStartOver = () => { clearProg(); setResume(null); setResults(null); setScopeData(null); setSeed(null); setStage('intro'); requestStart(); };
const level = scopeData ? scopeData.level : 'ml3';
return (
{stage === 'intro' && }
{stage === 'scope' && { setStage('intro'); window.scrollTo({ top: 0 }); }} saved={resume && resume.scope ? { ...resume.scope, level: resume.level } : null} />}
{stage === 'quiz' && { setStage('intro'); window.scrollTo({ top: 0 }); }} />}
{stage === 'results' && results && }
{gate && (
setGate(false)}
onSubmit={onGateSubmit} />
)}
);
};
Object.assign(window, { EvaluationCMMIPage });