import React, { useState, useEffect, useMemo } from 'react'; import { X, ChevronLeft, ChevronRight, Check } from 'lucide-react'; import { useAppConfig } from '../contexts/AppConfigContext'; const buildSteps = (config) => { const knowledgeLevels = (config?.login?.knowledge_levels || config?.login?.academic_stages || []) .filter((o) => o.value) .map((o) => ({ value: o.value, label: o.label })); const timezones = (config?.login?.timezones || []) .filter((o) => o.value) .map((o) => ({ value: o.value, label: o.label })); return [ { title: 'Background', fields: [ { key: 'knowledge_level', label: 'Cybersecurity knowledge level', type: 'select', options: knowledgeLevels.length ? knowledgeLevels : [ { value: 'newcomer', label: 'New to cybersecurity' }, { value: 'practitioner', label: 'Practitioner' }, ], }, { key: 'timezone', label: 'Time zone', type: 'select', options: timezones.length ? timezones : [{ value: 'UTC', label: 'UTC' }], }, ], }, { title: 'Role & environment', fields: [ { key: 'cyber_role', label: 'Your role', type: 'select', options: ['Student / Learner', 'Career changer', 'SOC analyst', 'Security engineer', 'Architect / lead', 'Manager / director', 'Consultant', 'Other'] }, { key: 'organization_type', label: 'Organization type', type: 'select', options: ['Startup', 'Mid-size company', 'Enterprise', 'Government / public sector', 'Education', 'MSP / MSSP', 'Independent / job seeker'] }, ], }, { title: 'Focus & tools', fields: [ { key: 'primary_domains', label: 'Primary domains (comma-separated)', type: 'text', placeholder: 'e.g. cloud, appsec, IR, GRC, identity' }, { key: 'certifications', label: 'Certifications (comma-separated)', type: 'text', placeholder: 'e.g. Security+, CISSP, OSCP, or none yet' }, { key: 'tools_stack', label: 'Tools & platforms (comma-separated)', type: 'text', placeholder: 'e.g. Splunk, CrowdStrike, AWS, Jira' }, ], }, { title: 'Goals & learning', fields: [ { key: 'compliance_focus', label: 'Compliance / frameworks', type: 'text', placeholder: 'e.g. SOC 2, NIST CSF, ISO 27001, HIPAA' }, { key: 'current_goals', label: 'Current goals', type: 'textarea', placeholder: 'Audit prep, cert study, incident readiness, architecture review...' }, { key: 'learning_preferences', label: 'How you learn best', type: 'text', placeholder: 'Labs, reading, CTFs, mentorship, certifications...' }, ], }, ]; }; const initFormFromProfile = (steps, profile) => { const init = {}; steps.forEach((s) => s.fields.forEach((f) => { const val = profile[f.key]; if (Array.isArray(val)) init[f.key] = val.join(', '); else if (val) init[f.key] = val; })); return init; }; const ProfileWalkthrough = ({ authToken, onClose, existingProfile }) => { const { config } = useAppConfig(); const steps = useMemo(() => buildSteps(config), [config]); const [step, setStep] = useState(0); const [formData, setFormData] = useState({}); const [saving, setSaving] = useState(false); const [loading, setLoading] = useState(true); useEffect(() => { let cancelled = false; const fetchProfile = async () => { try { const resp = await fetch(`${process.env.REACT_APP_API_URL}/api/users/me/profile`, { headers: { 'Authorization': `Bearer ${authToken}` }, }); if (resp.ok && !cancelled) { const profile = await resp.json(); setFormData(initFormFromProfile(steps, profile)); } } catch (e) { if (!cancelled && existingProfile) { setFormData(initFormFromProfile(steps, existingProfile)); } } finally { if (!cancelled) setLoading(false); } }; fetchProfile(); return () => { cancelled = true; }; }, [authToken, existingProfile, steps]); const handleChange = (key, value) => setFormData((prev) => ({ ...prev, [key]: value })); const saveProfile = async () => { const payload = { ...formData }; ['primary_domains', 'certifications', 'tools_stack'].forEach((k) => { if (typeof payload[k] === 'string') { payload[k] = payload[k].split(',').map((s) => s.trim()).filter(Boolean); } }); const hasData = Object.values(payload).some((v) => (Array.isArray(v) ? v.length > 0 : Boolean(v)) ); if (!hasData) return; try { await fetch(`${process.env.REACT_APP_API_URL}/api/users/me/profile`, { method: 'PUT', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); } catch (e) { console.error('Failed to save profile:', e); } }; const handleSave = async () => { setSaving(true); await saveProfile(); setSaving(false); onClose(); }; const handleClose = async () => { await saveProfile(); onClose(); }; const currentStep = steps[step]; const isLast = step === steps.length - 1; const renderSelectOptions = (options) => options.map((o) => { if (o && typeof o === 'object' && o.value != null) { return ; } return ; }); return (