const { useState, useMemo, useEffect, createElement: h } = React; function getOrdinalSuffix(day) { const mod100 = day % 100; if (mod100 >= 11 && mod100 <= 13) return 'th'; switch (day % 10) { case 1: return 'st'; case 2: return 'nd'; case 3: return 'rd'; default: return 'th'; } } function formatAssessmentDate(date) { const day = date.getDate(); const month = date.toLocaleString(undefined, { month: 'long' }); const year = date.getFullYear(); return `${day}${getOrdinalSuffix(day)} ${month} ${year}`; } function getDefaultAssessmentName(now = new Date()) { return `LVMWD - ${formatAssessmentDate(now)}`; } // Helper function to get maturity level based on score function getMaturityLevel(score) { if (score >= 80) return { name: 'Leading', color: '#3b82f6' }; if (score >= 60) return { name: 'Scaling', color: '#22c55e' }; if (score >= 40) return { name: 'Adopting', color: '#eab308' }; if (score >= 20) return { name: 'Experimenting', color: '#f97316' }; return { name: 'Curious/Aware', color: '#ef4444' }; } function AssessmentTool() { const [responses, setResponses] = useState({}); const [notes, setNotes] = useState({}); const [expandedSections, setExpandedSections] = useState( Object.fromEntries(assessmentData.dimensions.map((_, i) => [i, false])) ); const [showSaveDialog, setShowSaveDialog] = useState(false); const [showViewSaved, setShowViewSaved] = useState(false); const [organizationName, setOrganizationName] = useState(''); const [assessmentName, setAssessmentName] = useState(getDefaultAssessmentName()); const [activeQuestionId, setActiveQuestionId] = useState(null); const [showValidationErrors, setShowValidationErrors] = useState(false); const [autosaveState, setAutosaveState] = useState({ status: 'Saved', lastUpdated: null }); const draftStorageKey = 'aiMaturityAssessmentDraftV1'; const questionIndex = useMemo(() => { const order = []; const indexById = {}; assessmentData.dimensions.forEach((dimension, dimIndex) => { dimension.questions.forEach((question, qIndex) => { const globalIndex = order.length; order.push(question.id); indexById[question.id] = { dimIndex, qIndex, globalIndex }; }); }); return { order, indexById }; }, []); const unansweredQuestionIds = useMemo(() => { return questionIndex.order.filter(id => responses[id] === undefined); }, [questionIndex.order, responses]); const scrollToQuestion = (questionId) => { const meta = questionIndex.indexById[questionId]; if (!meta) return; setExpandedSections(prev => ({ ...prev, [meta.dimIndex]: true })); setActiveQuestionId(questionId); setTimeout(() => { const el = document.getElementById(questionId); if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'center' }); const input = el.querySelector('input'); if (input) input.focus({ preventScroll: true }); } }, 50); }; const goToUnanswered = (direction) => { if (unansweredQuestionIds.length === 0) { alert('All questions are answered.'); return; } const order = questionIndex.order; const startIndex = activeQuestionId && questionIndex.indexById[activeQuestionId] ? questionIndex.indexById[activeQuestionId].globalIndex : (direction > 0 ? -1 : order.length); const step = direction > 0 ? 1 : -1; const maxIters = order.length; let i = startIndex; for (let iter = 0; iter < maxIters; iter++) { i = (i + step + order.length) % order.length; const id = order[i]; if (responses[id] === undefined) { scrollToQuestion(id); return; } } scrollToQuestion(unansweredQuestionIds[0]); }; const validateAllAnswered = () => { const missing = unansweredQuestionIds; if (missing.length === 0) return { ok: true, missing: [] }; return { ok: false, missing }; }; // Load draft on first mount useEffect(() => { try { const raw = localStorage.getItem(draftStorageKey); if (!raw) return; const draft = JSON.parse(raw); if (draft && typeof draft === 'object') { if (draft.responses && typeof draft.responses === 'object') setResponses(draft.responses); if (draft.notes && typeof draft.notes === 'object') setNotes(draft.notes); if (typeof draft.organizationName === 'string') setOrganizationName(draft.organizationName); if (typeof draft.assessmentName === 'string' && draft.assessmentName.trim()) { setAssessmentName(draft.assessmentName); } if (draft.updatedAt) { const d = new Date(draft.updatedAt); if (!isNaN(d.getTime())) { setAutosaveState({ status: 'Saved', lastUpdated: d }); } } } } catch (_) { // Ignore draft load errors } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Calculate scores const calculations = useMemo(() => { const dimensionScores = assessmentData.dimensions.map(dimension => { let earnedPoints = 0; let totalPossiblePoints = 0; let answeredQuestions = 0; dimension.questions.forEach(question => { const maxPoints = Math.max(...question.options.map((_, i) => question.options[i]?.points || i * 3 + 3)); totalPossiblePoints += maxPoints; if (responses[question.id] !== undefined) { earnedPoints += question.options[responses[question.id]]?.points || responses[question.id] * 3 + 3; answeredQuestions++; } }); const percentage = totalPossiblePoints > 0 ? (earnedPoints / totalPossiblePoints) * 100 : 0; const completionRate = (answeredQuestions / dimension.questions.length) * 100; return { name: dimension.name, score: percentage, earnedPoints, totalPossiblePoints, weight: dimension.weight, completionRate, answeredQuestions, totalQuestions: dimension.questions.length }; }); let totalWeightedScore = 0; let totalWeight = 0; dimensionScores.forEach(dim => { totalWeightedScore += dim.score * dim.weight; totalWeight += dim.weight; }); const overallScore = totalWeight > 0 ? totalWeightedScore / totalWeight : 0; let maturityLevel = 'Curious/Aware'; let maturityColor = '#ef4444'; if (overallScore >= 80) { maturityLevel = 'Leading'; maturityColor = '#3b82f6'; } else if (overallScore >= 60) { maturityLevel = 'Scaling'; maturityColor = '#22c55e'; } else if (overallScore >= 40) { maturityLevel = 'Adopting'; maturityColor = '#eab308'; } else if (overallScore >= 20) { maturityLevel = 'Experimenting'; maturityColor = '#f97316'; } const totalAnswered = dimensionScores.reduce((s, d) => s + d.answeredQuestions, 0); const totalQuestions = dimensionScores.reduce((s, d) => s + d.totalQuestions, 0); return { dimensionScores, overallScore, maturityLevel, maturityColor, totalAnswered, totalQuestions }; }, [responses]); // Initialize Chart.js radar chart useEffect(() => { const ctx = document.getElementById('radarChart'); if (!ctx) return; if (window.radarChartInstance) { window.radarChartInstance.destroy(); } window.radarChartInstance = new Chart(ctx.getContext('2d'), { type: 'radar', data: { labels: calculations.dimensionScores.map(d => d.name), datasets: [{ label: 'Maturity Score', data: calculations.dimensionScores.map(d => d.score), fill: true, backgroundColor: 'rgba(59, 130, 246, 0.2)', borderColor: 'rgba(59, 130, 246, 1)', pointBackgroundColor: 'rgba(59, 130, 246, 1)', pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff', pointHoverBorderColor: 'rgba(59, 130, 246, 1)', pointRadius: 5, pointHoverRadius: 7 }] }, options: { responsive: true, maintainAspectRatio: true, scales: { r: { beginAtZero: true, max: 100, ticks: { stepSize: 20, callback: value => value + '%' }, pointLabels: { font: { size: 11 } } } }, plugins: { legend: { display: false }, tooltip: { callbacks: { label: context => context.parsed.r.toFixed(1) + '%' } } } } }); return () => { if (window.radarChartInstance) { window.radarChartInstance.destroy(); } }; }, [calculations]); const handleResponse = (questionId, value) => { setResponses(prev => ({ ...prev, [questionId]: value })); setActiveQuestionId(questionId); }; const toggleSection = (index) => { setExpandedSections(prev => ({ ...prev, [index]: !prev[index] })); }; const exportAssessment = () => { const validation = validateAllAnswered(); if (!validation.ok) { setShowValidationErrors(true); scrollToQuestion(validation.missing[0]); alert(`Please answer all questions before finalizing. Remaining: ${validation.missing.length}`); return; } const data = { assessmentName: assessmentName || "AI Maturity Assessment", organizationName: organizationName || "", timestamp: new Date().toISOString(), responses: responses, notes: notes, scores: calculations }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `assessment-${new Date().toISOString().split('T')[0]}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const loadAssessment = () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.onchange = (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { try { const data = JSON.parse(event.target.result); if (data.responses) { setResponses(data.responses); } if (data.notes && typeof data.notes === 'object') setNotes(data.notes); if (typeof data.organizationName === 'string') setOrganizationName(data.organizationName); if (typeof data.assessmentName === 'string' && data.assessmentName.trim()) setAssessmentName(data.assessmentName); } catch (error) { alert('Failed to load file'); } }; reader.readAsText(file); }; input.click(); }; const copyToClipboard = () => { const text = `AI Maturity Assessment Results Overall Score: ${calculations.overallScore.toFixed(1)}% Maturity Level: ${calculations.maturityLevel} Progress: ${calculations.totalAnswered}/${calculations.totalQuestions} questions Dimension Scores: ${calculations.dimensionScores.map(d => `${d.name}: ${d.score.toFixed(1)}% (${d.answeredQuestions}/${d.totalQuestions} answered)` ).join('\n')}`; navigator.clipboard.writeText(text).then(() => alert('Copied to clipboard!')); }; const saveAssessmentToCloud = () => { if (!organizationName.trim()) { alert('Please enter an organization name'); return; } const data = { assessmentName: assessmentName || getDefaultAssessmentName(), organizationName: organizationName.trim(), timestamp: new Date().toISOString(), responses: responses, notes: notes, scores: calculations }; // Get existing assessments const saved = JSON.parse(localStorage.getItem('savedAssessments') || '[]'); saved.push(data); localStorage.setItem('savedAssessments', JSON.stringify(saved)); alert('Assessment saved successfully!'); setShowSaveDialog(false); // Reset everything for a fresh assessment setResponses({}); setNotes({}); setOrganizationName(''); setAssessmentName(getDefaultAssessmentName()); setActiveQuestionId(null); setShowValidationErrors(false); setExpandedSections(Object.fromEntries(assessmentData.dimensions.map((_, i) => [i, false]))); localStorage.removeItem(draftStorageKey); window.scrollTo({ top: 0, behavior: 'smooth' }); }; const getSavedAssessments = () => { return JSON.parse(localStorage.getItem('savedAssessments') || '[]'); }; const loadSavedAssessment = (index) => { const saved = getSavedAssessments(); if (saved[index]) { setResponses(saved[index].responses); if (saved[index].notes && typeof saved[index].notes === 'object') setNotes(saved[index].notes); setOrganizationName(saved[index].organizationName); if (typeof saved[index].assessmentName === 'string' && saved[index].assessmentName.trim()) { setAssessmentName(saved[index].assessmentName); } setShowViewSaved(false); alert('Assessment loaded!'); } }; // Autosave draft (debounced) useEffect(() => { setAutosaveState(prev => ({ ...prev, status: 'Saving…' })); const timer = setTimeout(() => { try { const updatedAt = new Date(); const draft = { assessmentName, organizationName, responses, notes, updatedAt: updatedAt.toISOString() }; localStorage.setItem(draftStorageKey, JSON.stringify(draft)); setAutosaveState({ status: 'Saved', lastUpdated: updatedAt }); } catch (_) { setAutosaveState(prev => ({ ...prev, status: 'Saved' })); } }, 500); return () => clearTimeout(timer); }, [assessmentName, organizationName, responses, notes]); const deleteSavedAssessment = (index) => { if (confirm('Are you sure you want to delete this assessment?')) { const saved = getSavedAssessments(); saved.splice(index, 1); localStorage.setItem('savedAssessments', JSON.stringify(saved)); setShowViewSaved(false); setTimeout(() => setShowViewSaved(true), 0); } }; return h('div', { className: 'min-h-screen bg-gray-50' }, h('div', { className: 'max-w-7xl mx-auto p-6' }, // Header Card h('div', { className: 'bg-white rounded-lg shadow-lg p-4 md:p-6 mb-4' }, h('div', { className: 'flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-4' }, h('div', { className: 'flex items-center gap-4' }, h('img', { src: 'LOGO1.png', alt: 'Sedna Consulting Group', className: 'h-8 md:h-10' }), h('div', {}, h('h1', { className: 'text-xl md:text-2xl font-bold text-gray-900' }, 'AI Maturity Assessment'), h('p', { className: 'text-xs md:text-sm text-gray-600' }, `Progress: ${calculations.totalAnswered} of ${calculations.totalQuestions} questions`), h('div', { className: 'mt-2 flex flex-col sm:flex-row sm:items-center gap-2' }, h('input', { type: 'text', value: assessmentName, onChange: (e) => setAssessmentName(e.target.value), placeholder: 'Assessment name', className: 'w-full sm:w-[360px] px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500' }), h('div', { className: 'text-xs text-gray-500' }, autosaveState.status === 'Saving…' ? 'Saving…' : `Saved${autosaveState.lastUpdated ? ` • Last updated ${autosaveState.lastUpdated.toLocaleString()}` : ''}` ) ) ) ), h('div', { className: 'flex flex-wrap gap-2 no-print' }, h('button', { onClick: () => setShowSaveDialog(true), className: 'px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium' }, 'Save'), h('button', { onClick: () => setShowViewSaved(true), className: 'px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 font-medium' }, 'Load'), h('button', { onClick: exportAssessment, className: 'px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 font-medium' }, unansweredQuestionIds.length > 0 ? `Finalize (${unansweredQuestionIds.length} left)` : 'Finalize'), h('button', { onClick: () => window.print(), className: 'px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 font-medium' }, 'Print') ) ), h('div', { className: 'text-center py-4' }, h('div', { className: 'text-4xl md:text-5xl font-bold mb-1', style: { color: calculations.maturityColor } }, `${calculations.overallScore.toFixed(1)}%`), h('div', { className: 'text-lg md:text-xl font-semibold', style: { color: calculations.maturityColor } }, calculations.maturityLevel) ) ), // Unanswered Navigation (kept above the question sections) h('div', { className: 'bg-white rounded-lg shadow-md p-3 mb-4 no-print flex flex-wrap gap-2 justify-end items-center' }, h('div', { className: 'text-sm text-gray-600 mr-auto' }, unansweredQuestionIds.length > 0 ? `${unansweredQuestionIds.length} unanswered remaining` : 'All questions answered' ), h('button', { onClick: () => goToUnanswered(-1), className: 'px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 font-medium' }, 'Previous Unanswered'), h('button', { onClick: () => goToUnanswered(1), className: 'px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 font-medium' }, 'Next Unanswered') ), // Radar Chart Card - Smaller h('div', { className: 'bg-white rounded-lg shadow-lg p-4 md:p-6 mb-4' }, h('h2', { className: 'text-lg font-bold text-gray-900 mb-3 text-center' }, 'Maturity Dimensions'), h('div', { className: 'max-w-md mx-auto', style: { height: '280px' } }, h('canvas', { id: 'radarChart' }) ) ), // Dimension Summary Cards h('div', { className: 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-4' }, ...assessmentData.dimensions.map((dimension, dimIndex) => { const dimScore = calculations.dimensionScores[dimIndex]; const pct = dimScore.score; const levelColor = getMaturityLevel(pct).color; return h('div', { key: `summary-${dimIndex}`, className: 'bg-white rounded-lg shadow-md p-4 cursor-pointer hover:shadow-lg transition-shadow', onClick: () => { setExpandedSections(prev => ({ ...prev, [dimIndex]: true })); setTimeout(() => { const el = document.getElementById(dimension.questions[0].id); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 100); } }, h('div', { className: 'flex items-center justify-between mb-2' }, h('h3', { className: 'font-semibold text-gray-900 text-sm' }, dimension.name), h('span', { className: 'text-2xl font-bold', style: { color: levelColor } }, `${pct.toFixed(0)}%`) ), h('p', { className: 'text-xs text-gray-500 mb-2' }, `${dimScore.answeredQuestions}/${dimScore.totalQuestions} questions`), h('div', { className: 'w-full bg-gray-200 rounded-full h-2' }, h('div', { className: 'h-2 rounded-full transition-all', style: { width: `${pct}%`, backgroundColor: levelColor } }) ) ); }) ), // Save Dialog Modal showSaveDialog && h('div', { className: 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50', onClick: () => setShowSaveDialog(false) }, h('div', { className: 'bg-white rounded-lg p-6 max-w-md w-full mx-4', onClick: (e) => e.stopPropagation() }, h('h3', { className: 'text-xl font-bold mb-4' }, 'Save Assessment'), h('input', { type: 'text', placeholder: 'Assessment name', value: assessmentName, onChange: (e) => setAssessmentName(e.target.value), className: 'w-full px-4 py-2 border border-gray-300 rounded-lg mb-3 focus:outline-none focus:ring-2 focus:ring-blue-500' }), h('input', { type: 'text', placeholder: 'Enter organization name', value: organizationName, onChange: (e) => setOrganizationName(e.target.value), className: 'w-full px-4 py-2 border border-gray-300 rounded-lg mb-4 focus:outline-none focus:ring-2 focus:ring-blue-500' }), h('div', { className: 'flex gap-2 justify-end' }, h('button', { onClick: () => setShowSaveDialog(false), className: 'px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600' }, 'Cancel'), h('button', { onClick: saveAssessmentToCloud, className: 'px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700' }, 'Save') ) ) ), // View Saved Assessments Modal showViewSaved && h('div', { className: 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4', onClick: () => setShowViewSaved(false) }, h('div', { className: 'bg-white rounded-lg p-6 max-w-4xl w-full max-h-[80vh] overflow-y-auto', onClick: (e) => e.stopPropagation() }, h('div', { className: 'flex justify-between items-center mb-4' }, h('h3', { className: 'text-xl font-bold' }, 'Saved Assessments'), h('button', { onClick: () => setShowViewSaved(false), className: 'text-gray-500 hover:text-gray-700 text-2xl' }, '×') ), getSavedAssessments().length === 0 ? h('p', { className: 'text-gray-500 text-center py-8' }, 'No saved assessments yet') : h('div', { className: 'space-y-4' }, ...getSavedAssessments().map((assessment, index) => h('div', { key: index, className: 'border border-gray-200 rounded-lg p-4 hover:bg-gray-50' }, h('div', { className: 'flex justify-between items-start mb-2' }, h('div', {}, h('h4', { className: 'font-bold text-lg' }, assessment.assessmentName || 'Untitled Assessment'), h('p', { className: 'text-sm text-gray-700' }, assessment.organizationName), h('p', { className: 'text-sm text-gray-500' }, new Date(assessment.timestamp).toLocaleString() ) ), h('div', { className: 'flex gap-2' }, h('button', { onClick: () => loadSavedAssessment(index), className: 'px-3 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm' }, 'Load'), h('button', { onClick: () => deleteSavedAssessment(index), className: 'px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700 text-sm' }, 'Delete') ) ), h('div', { className: 'text-sm' }, h('p', {}, h('span', { className: 'font-semibold' }, 'Score: '), h('span', { style: { color: assessment.scores.maturityColor } }, `${assessment.scores.overallScore.toFixed(1)}% - ${assessment.scores.maturityLevel}`) ), h('p', {}, h('span', { className: 'font-semibold' }, 'Progress: '), `${assessment.scores.totalAnswered}/${assessment.scores.totalQuestions} questions` ) ) ) ) ) ) ), // Dimensions ...assessmentData.dimensions.map((dimension, dimIndex) => h('div', { key: dimIndex, className: 'bg-white rounded-lg shadow-md mb-4 overflow-hidden' }, // Dimension Header h('div', { className: 'bg-gray-50 border-b border-gray-200 p-4 md:p-5 cursor-pointer hover:bg-gray-100', onClick: () => toggleSection(dimIndex) }, h('div', { className: 'flex items-center justify-between' }, h('div', {}, h('h3', { className: 'text-lg md:text-xl font-bold text-gray-900' }, dimension.name) ), h('div', { className: 'flex items-center gap-4 text-sm text-gray-600' }, h('span', {}, `${calculations.dimensionScores[dimIndex].answeredQuestions}/${dimension.questions.length} answered`), h('span', {}, `Score: ${calculations.dimensionScores[dimIndex].score.toFixed(1)}%`), h('span', {}, `Weight: ${dimension.weight} pts`), h('svg', { className: `w-6 h-6 transform transition-transform ${expandedSections[dimIndex] ? 'rotate-180' : ''}`, fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24' }, h('path', { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M19 9l-7 7-7-7' }) ) ) ) ), // Questions expandedSections[dimIndex] && h('div', { className: 'p-4 md:p-6' }, ...dimension.questions.map((question, qIndex) => { const isUnanswered = responses[question.id] === undefined; const showRequired = showValidationErrors && isUnanswered; return h('div', { id: question.id, key: question.id, className: `mb-6 pb-6 border-b border-gray-200 last:border-b-0 last:mb-0 last:pb-0 ${showRequired ? 'ring-2 ring-red-400 rounded-lg p-3 -m-3' : ''}` }, h('div', { className: 'mb-3' }, h('div', { className: 'flex items-start gap-2' }, h('span', { className: 'text-blue-600 font-semibold flex-shrink-0' }, `${qIndex + 1}.`), h('div', { className: 'flex-1' }, h('p', { className: `font-medium ${showRequired ? 'text-red-700' : 'text-gray-900'}` }, question.text), showRequired && h('p', { className: 'text-xs text-red-600 mt-1' }, 'Required') ) ) ), h('div', { className: 'space-y-2 ml-6' }, ...question.options.map((option, optIndex) => { const isSelected = responses[question.id] === optIndex; const points = option.points !== undefined ? option.points : optIndex * 3 + 3; return h('label', { key: optIndex, className: `flex items-start gap-3 p-3 border-2 rounded-lg cursor-pointer transition-all ${isSelected ? 'border-blue-500 bg-blue-50' : 'border-gray-200 hover:border-blue-300 hover:bg-gray-50' }` }, h('input', { type: 'radio', name: question.id, value: optIndex, checked: isSelected, onChange: () => handleResponse(question.id, optIndex), className: 'mt-1 w-5 h-5 text-blue-600 flex-shrink-0' }), h('div', { className: 'flex-1' }, h('div', { className: 'font-semibold text-gray-900 mb-1' }, option.level || ['Curious/Aware', 'Experimenting', 'Adopting', 'Scaling', 'Leading'][optIndex] ), h('div', { className: 'text-sm text-gray-600' }, option.description || option ) ), h('div', { className: 'text-sm font-medium text-gray-500 flex-shrink-0' }, `${points} pts` ) ); }) ), h('div', { className: 'ml-6 mt-3' }, h('label', { className: 'block text-sm font-medium text-gray-700 mb-1' }, 'Notes'), h('textarea', { value: notes[question.id] || '', onChange: (e) => setNotes(prev => ({ ...prev, [question.id]: e.target.value })), placeholder: 'Add your notes here...', rows: 2, className: 'w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 resize-y' }) ) ); }) ) ) ) ) ); } // Render the app ReactDOM.createRoot(document.getElementById('root')).render(h(AssessmentTool));