// EvaluationNIST.jsx — Verigo Global: HITRUST CSF online readiness evaluation (assessment-driven, resumable)
const { V: EV, MAXW: EMW, FONT: EFT } = window;
/* ── PROGRESS PERSISTENCE ─────────────────────────────────── */
const H_PROG_KEY = 'verigo_nist_eval';
const hLoadProg = () => { try { return JSON.parse(localStorage.getItem(H_PROG_KEY) || 'null'); } catch (e) { return null; } };
const hSaveProg = (p) => { try { localStorage.setItem(H_PROG_KEY, JSON.stringify(p)); } catch (e) {} };
const hClearProg = () => { try { localStorage.removeItem(H_PROG_KEY); } catch (e) {} };
const hPreviewThemes = [
['briefcase', 'GV · Govern', 60],
['shield', 'PR · Protect', 66],
['activity', 'DE · Detect', 52],
['zap', 'RS · Respond', 68],
];
/* ── RESUME BANNER ───────────────────────────────────────── */
const NiResumeBanner = ({ 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 assess = prog.assessment ? prog.assessment.toUpperCase() : '';
return (
{done ? 'Your last evaluation is complete and saved.' : 'You have an evaluation in progress.'}
{prog.scope && prog.scope.company ? prog.scope.company + ' · ' : ''}{assess ? assess + ' · ' : ''}{when ? 'Saved ' + when : 'Pick up where you left off.'}
{done ? 'View saved results' : 'Resume evaluation'}
Start over
);
};
/* ── PREVIEW DASHBOARD ───────────────────────────────────── */
const NiScorePreview = () => (
Readiness report
Sample · i1
Overall maturity
Established
54 of 147 references need attention.
{hPreviewThemes.map(([ic, name, pct], i) => (
))}
);
/* ── INTRO STAGE ─────────────────────────────────────────── */
const NiEvalIntro = ({ onStart, onNav, resume, onResume, onStartOver }) => {
const steps = [
['target', 'Pick your assessment type', 'Choose e1, i1, or r2 — your choice tailors the evaluation to the categories and depth that apply to that assessment.'],
['gauge', 'Instant scoring', 'Get a maturity score with a category-by-category breakdown showing exactly where you stand against the CSF.'],
['flag', 'Mapped action plan', 'Every gap links straight to the toolkit document or control reference that closes it — so you know the next move for MyCSF.'],
];
return (
{resume &&
}
onNav('toolkit:nist')} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#7A7A8A', fontSize: 13, fontWeight: 600, padding: 0, fontFamily: EFT }}>NIST CSF Toolkit
/
Online Evaluation
Tier-aware · ~10 minutes · free
Know where you stand on NIST CSF v2.0.
Measure your current state against the HITRUST CSF for the assessment type you're targeting. Pick your assessment type in scope and the evaluation asks only the categories and controls 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_NIST = {
industry: ['Federal / government', 'Defense contractor', 'Financial services', 'Healthcare', 'Critical infrastructure', 'Software / SaaS', 'Higher education', 'Other'],
employees: ['1–50', '51–200', '201–1,000', '1,000+'],
region: ['United States', 'United Kingdom', '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'],
};
// HITRUST assessment types — the key scope choice that drives the evaluation.
const HITRUST_ASSESS_OPTIONS = [
['tier1', 'Tier 1 — Partial', 'Ad hoc', 'No certification', 'Informal, reactive practices — risk management is not formalized.'],
['tier2', 'Tier 2 — Risk Informed', 'Risk-aware', 'No certification', 'Risk-aware but inconsistently applied — practices vary across the org.'],
['tier3', 'Tier 3 — Repeatable', 'Formal + consistent', 'No certification', 'Approved, org-wide practices — the most commonly targeted tier.'],
['tier4', 'Tier 4 — Adaptive', 'Continuously optimized', 'No certification', 'Continuously adapted based on threats and business objectives.'],
];
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 NiScopeForm = ({ onSubmit, onBack, saved }) => {
const u = (() => { try { return window.TK_NIST.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_HITRUST.industry[0], employees: sv.employees || u.employees || SCOPE_FIELDS_HITRUST.employees[0],
region: sv.region || u.region || SCOPE_FIELDS_HITRUST.region[0], locations: sv.locations || u.locations || SCOPE_FIELDS_HITRUST.locations[0],
systems: sv.systems || u.systems || '', certs: sv.certs || u.certs || '', target: sv.target || u.target || SCOPE_FIELDS_HITRUST.target[1],
});
const [assessment, setAssessment] = React.useState(() => (saved && saved.assessment) ? saved.assessment : 'i1');
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_NIST[k].map((o) => {o} )}
;
const chosen = HITRUST_ASSESS_OPTIONS.find((o) => o[0] === assessment);
return (
Step 1 of 2 · Scope your assessment
Tell us about your organization
Pick your target HITRUST assessment type — that choice sets which categories we evaluate. Then fill in a few details to tailor your results.
);
};
/* ── PAGE ────────────────────────────────────────────────── */
const EvaluationNISTPage = ({ onNav }) => {
const [stage, setStage] = React.useState('intro');
const [gate, setGate] = React.useState(false);
const [results, setResults] = React.useState(null);
const [user, setUser] = React.useState(null);
const [scopeData, setScopeData] = React.useState(null);
const [resume, setResume] = React.useState(null);
const [seed, setSeed] = React.useState(null);
React.useEffect(() => {
try { setUser(window.TK_NIST.getUser()); } catch (e) {}
const p = hLoadProg();
if (p && p.stage && p.stage !== 'intro') setResume(p);
}, []);
const persist = (patch) => { const base = hLoadProg() || {}; hSaveProg({ ...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_NIST.getUser()); setStage('scope'); window.scrollTo({ top: 0 }); }
else { setGate(true); }
};
const onGateSubmit = (form) => {
window.TK_NIST.storeLead({ ...form, source: 'evaluation' });
try { sessionStorage.setItem('verigo_contact_ok', '1'); } catch (e) {}
setUser(window.TK_NIST.getUser());
setGate(false);
setStage('scope');
window.scrollTo({ top: 0 });
};
const onScopeSubmit = (form) => {
const assessment = form.assessment || 'i1';
window.TK_NIST.storeLead({ ...form, source: 'evaluation-scope' });
setUser(window.TK_NIST.getUser());
setScopeData({ form, assessment });
setSeed({ answers: {}, step: 0 });
hSaveProg({ stage: 'quiz', scope: form, assessment, 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, tier: p.assessment || 'i1' });
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 = () => { hClearProg(); setResume(null); setResults(null); setScopeData(null); setSeed(null); setStage('intro'); requestStart(); };
const assessment = scopeData ? scopeData.assessment : 'i1';
return (
{stage === 'intro' && }
{stage === 'scope' && { setStage('intro'); window.scrollTo({ top: 0 }); }} saved={resume && resume.scope ? { ...resume.scope, assessment: resume.assessment } : null} />}
{stage === 'quiz' && { setStage('intro'); window.scrollTo({ top: 0 }); }} />}
{stage === 'results' && results && }
{gate && (
setGate(false)}
onSubmit={onGateSubmit} />
)}
);
};
Object.assign(window, { EvaluationNISTPage });