'use client'; import { notFound } from 'next/navigation'; import { useEffect, useState, useMemo, use, useRef } from 'react'; import { Button } from '@/components/ui/button'; import { Questionnaire } from '@/types'; import Link from 'next/link'; import { ResultContainer } from '@/components/questionnaire/result/public/ResultContainer'; import { AnswerList } from '@/components/questionnaire/result/public/AnswerList'; import { ResultAnalysis } from '@/components/questionnaire/result/analysis/ResultAnalysis'; import { useQuestionnaire } from '@/hooks/useQuestionnaire'; import { useScopedI18n } from '@/locales/client'; import { loadResult } from '@/lib/result-storage'; import { AssessmentRecord } from '@/lib/assessment-types'; import { getProfiles, getRecords, updateRecordAnalysis } from '@/lib/assessment-db'; import { syncAnonymousRecord } from '@/lib/anonymous-client'; export default function QuestionnaireResultPage({ params, }: { params: Promise<{ id: string }>; }) { const { id } = use(params); const [loading, setLoading] = useState(true); const [decodedAnswers, setDecodedAnswers] = useState(null); const [record, setRecord] = useState(null); const [profileName, setProfileName] = useState('未命名档案'); const analysisRef = useRef(null); const t = useScopedI18n('app.questionnaire.result'); // Get the questionnaire with specified id from questionnaire data const questionnaire = useQuestionnaire(id) as Questionnaire; const recordId = record?.id; // Load results from tab-local storage. Answers are intentionally not kept in the URL. useEffect(() => { if (!questionnaire || !questionnaire.details) { return; } const stored = loadResult(id); setDecodedAnswers(stored?.answers || null); async function loadRecord() { if (stored?.profileId) { const profiles = await getProfiles(); setProfileName(profiles.find((profile) => profile.id === stored.profileId)?.name || '未命名档案'); } if (stored?.recordId) { const records = await getRecords(stored.profileId); setRecord(records.find((item) => item.id === stored.recordId) || null); } setLoading(false); } void loadRecord(); }, [id, questionnaire]); useEffect(() => { if (!recordId || !analysisRef.current) return; const timer = window.setTimeout(() => { const text = analysisRef.current?.innerText.trim() || ''; if (!text) return; if (record?.analysisText === text) return; const updated = record ? { ...record, analysisText: text } : null; setRecord(updated); void updateRecordAnalysis(recordId, text); if (updated) { void syncAnonymousRecord(updated).catch((error) => { console.error('Failed to sync anonymous record analysis:', error); }); } }, 100); return () => window.clearTimeout(timer); }, [record, recordId]); // Construct question-option text pairs for copying result data const questionnaireResults: Record = useMemo(() => { if (!questionnaire || !decodedAnswers) return {}; const obj: Record = {}; questionnaire.questions.forEach((q, idx) => { const val = decodedAnswers[idx]; if (val === undefined) return; const option = questionnaire.renderOptions(q.id).find( (o) => String(o.value) === String(val) ); obj[q.content] = option ? option.content : String(val); }); return obj; }, [decodedAnswers, questionnaire]); // If data not found, show 404 page if (!questionnaire || !questionnaire.details) { return notFound(); } if (loading) { return (
); } if (!decodedAnswers || decodedAnswers.length !== questionnaire.questions.length) { return (

{questionnaire.title} - {t('resultNotFoundTitle')}

{t('resultNotFoundDesc')}

); } return (
); }