Files
MindScope/components/questionnaire/result/public/ResultContainer.tsx
T

144 lines
4.9 KiB
TypeScript

import Link from 'next/link';
import { ReactNode } from 'react';
import { Button } from '@/components/ui/button';
import { useScopedI18n } from '@/locales/client';
import { Copy, Download, FileText } from 'lucide-react';
import { toast } from 'sonner';
import { Questionnaire } from '@/types';
import { AssessmentRecord } from '@/lib/assessment-types';
import { recordToMarkdown } from '@/lib/assessment-export';
interface ResultContainerProps {
title: string;
id: string;
children: ReactNode;
questionnaire?: Questionnaire;
answers?: string[];
questionnaireResults?: Record<string, string>;
record?: AssessmentRecord;
profileName?: string;
}
export function ResultContainer({ title, id, children, questionnaire, answers, questionnaireResults, record, profileName = '未命名档案' }: ResultContainerProps) {
const t = useScopedI18n(
'component.questionnaire.result.public.resultContainer'
);
const handleCopyResultLink = async () => {
try {
await navigator.clipboard.writeText(
`${window.location.origin}${window.location.pathname}`,
);
toast.success(t('copySuccess'));
} catch {
toast.error(t('copyError'));
}
};
const buildResultMarkdown = () => {
if (record) {
return recordToMarkdown(record, profileName);
}
if (!questionnaire || !answers || !questionnaireResults) {
return null;
}
const currentTime = new Date().toLocaleString();
let resultData = `# ${t('copyTemplate.title')}\n\n`;
resultData += `## ${t('copyTemplate.basicInfo')}\n`;
resultData += `- ${t('copyTemplate.questionnaireName')}: ${questionnaire.title}\n`;
resultData += `- ${t('copyTemplate.questionnaireId')}: ${id}\n`;
resultData += `- ${t('copyTemplate.assessmentTime')}: ${currentTime}\n`;
resultData += `- ${t('copyTemplate.questionCount')}: ${questionnaire.questions.length}\n\n`;
resultData += `## ${t('copyTemplate.questionsAndAnswers')}\n`;
Object.entries(questionnaireResults).forEach(([question, answer], index) => {
resultData += `${index + 1}. ${question}\n ${t('copyTemplate.answer')}: ${answer}\n\n`;
});
resultData += `## ${t('copyTemplate.usage')}\n`;
resultData += `${t('copyTemplate.disclaimer')}\n\n`;
resultData += `${t('copyTemplate.source')}: ${t('copyTemplate.platform')}\n`;
resultData += `${t('copyTemplate.website')}: ${window.location.origin}\n`;
return resultData;
};
const handleCopyResultData = async () => {
const resultData = buildResultMarkdown();
if (!resultData) {
toast.error(t('copyResultDataError'));
return;
}
try {
await navigator.clipboard.writeText(resultData);
toast.success(t('copyResultDataSuccess'));
} catch {
toast.error(t('copyResultDataError'));
}
};
const handleDownloadResultData = () => {
const resultData = buildResultMarkdown();
if (!resultData) {
toast.error(t('downloadResultDataError'));
return;
}
const blob = new Blob([resultData], { type: 'text/markdown;charset=utf-8' });
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = `${id}-result.md`;
anchor.click();
URL.revokeObjectURL(url);
toast.success(t('downloadResultDataSuccess'));
};
return (
<div className="flex justify-center items-center min-h-screen md:p-4 p-2">
<div className="max-w-6xl w-full bg-white rounded-lg shadow-lg md:p-8 p-4 border">
<h1 className="text-2xl font-bold mb-6">
{title} - {t('resultText')}
</h1>
<div className="mb-8">
<div className="space-y-6">{children}</div>
</div>
<div className="flex flex-col sm:flex-row sm:justify-between gap-4 mt-8">
<Button variant="outline" className="w-full sm:w-auto">
<Link href={`/questionnaire/${id}`}>{t('backToDetail')}</Link>
</Button>
<div className="flex flex-col sm:flex-row gap-2 w-full sm:w-auto">
<Button variant="outline" onClick={handleCopyResultLink} className="w-full sm:w-auto">
<Copy className="w-4 h-4 mr-2" />
{t('copyResultLink')}
</Button>
<Button
variant="outline"
onClick={handleCopyResultData}
className="w-full sm:w-auto"
>
<FileText className="w-4 h-4 mr-2" />
{t('copyResultData')}
</Button>
<Button
variant="outline"
onClick={handleDownloadResultData}
className="w-full sm:w-auto"
>
<Download className="w-4 h-4 mr-2" />
{t('downloadResultData')}
</Button>
<Button asChild className="w-full sm:w-auto">
<Link href="/records">查看测评档案</Link>
</Button>
</div>
</div>
</div>
</div>
);
}