import { useState, useEffect } from 'react' import { adminApi, type SurveyResponseDetail, type SurveyResponseListResponse } from '@/api/admin' import { PageHeader } from '@/components/admin' import { ChevronDown, Download, User, Link2, Loader2 } from 'lucide-react' import { cn } from '@/lib/utils' const QUESTIONS: { id: string; num: string; text: string; type: 'mc' | 'mc-multi' | 'range' | 'text' | 'rank' }[] = [ { id: 'prereqs', num: '1', text: 'Before you start troubleshooting, what info do you need?', type: 'mc-multi' }, { id: 'verify_fix', num: '2', text: 'After you apply a fix, how do you verify it actually worked?', type: 'mc' }, { id: 'steps_at_a_time', num: '3', text: 'How many steps do you prefer to see at once?', type: 'range' }, { id: 'first_step', num: '4', text: 'A vague ticket comes in: "Internet is down." What\'s your FIRST move?', type: 'mc' }, { id: 'junior_mistake', num: '5', text: 'Most common mistake you see junior engineers make?', type: 'mc' }, { id: 'pivot', num: '6', text: 'How do you decide when to stop pursuing one theory and pivot?', type: 'mc' }, { id: 'scenario_approach', num: '7', text: 'Walk through your first 3 diagnostic steps for this ticket.', type: 'text' }, { id: 'scenario_deeper', num: '8', text: 'Server pings fine, you can RDP in. What do you check next?', type: 'text' }, { id: 'doc_pct', num: '9', text: 'What percentage of troubleshooting steps do you actually document?', type: 'range' }, { id: 'go_to_commands', num: '10', text: 'Top 3 go-to PowerShell commands or one-liners?', type: 'text' }, { id: 'secret_weapon', num: '11', text: 'Secret weapon command/tool/technique?', type: 'text' }, { id: 'gotcha', num: '12', text: 'Issue where the obvious diagnosis was WRONG?', type: 'text' }, { id: 'hard_rules', num: '13', text: 'Which "rules" do you follow?', type: 'mc-multi' }, { id: 'prioritization', num: '14', text: 'Rank factors by diagnostic priority influence.', type: 'rank' }, { id: 'detail_level', num: '15', text: 'How specific should AI diagnostic suggestions be?', type: 'mc' }, { id: 'ai_personality', num: '16', text: 'What makes an AI feel like a useful colleague?', type: 'mc' }, ] function AnswerDisplay({ value, type }: { value: string | string[] | undefined; type: string }) { if (!value || (Array.isArray(value) && value.length === 0)) { return

No answer

} if (type === 'mc-multi' && Array.isArray(value)) { return (
{value.map((v, i) => ( {v} ))}
) } if (type === 'rank' && Array.isArray(value)) { return (
    {value.map((v, i) => (
  1. {i + 1}. {v}
  2. ))}
) } if (type === 'text') { return (

{String(value)}

) } return

{String(value)}

} function ExpandedDetail({ response }: { response: SurveyResponseDetail }) { return (
{QUESTIONS.map((q) => (

Q{q.num}

{q.text}

))}
) } function ResponseRow({ response, index, isExpanded, onToggle, }: { response: SurveyResponseDetail index: number isExpanded: boolean onToggle: () => void }) { const answeredCount = QUESTIONS.filter((q) => { const val = response.responses[q.id] return val !== undefined && val !== null && val !== '' && !(Array.isArray(val) && val.length === 0) }).length return ( <> {index + 1} {response.respondent_name || Anonymous} {response.source === 'invite' ? ( Invite {response.invite_name && ( ({response.invite_name}) )} ) : ( Direct )} {new Date(response.created_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', })} {answeredCount} / {QUESTIONS.length} {isExpanded && } ) } export default function SurveyResponsesPage() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [expandedId, setExpandedId] = useState(null) const [exporting, setExporting] = useState(false) useEffect(() => { const fetchData = async () => { try { const result = await adminApi.listSurveyResponses() setData(result) } catch { setError('Failed to load survey responses') } finally { setLoading(false) } } fetchData() }, []) const handleExport = async () => { setExporting(true) try { const blob = await adminApi.exportSurveyResponsesCsv() const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = 'survey-responses.csv' a.click() URL.revokeObjectURL(url) } catch { setError('Export failed') } finally { setExporting(false) } } if (loading) { return (
) } if (error && !data) { return (
{error}
) } const responses = data?.responses ?? [] return (
{exporting ? ( ) : ( )} Export CSV } /> {error && (
{error}
)} {/* Stat cards */}

Total Responses

{data?.total ?? 0}

This Week

{data?.this_week ?? 0}

{/* Table */}
{responses.length === 0 ? ( ) : ( responses.map((response, index) => ( setExpandedId(expandedId === response.id ? null : response.id) } /> )) )}
# Respondent Source Date Answered
No survey responses yet.
) }