feat: 完善中文心理测评平台
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
'use client';
|
||||
|
||||
import { calculateGritResults } from '../../test/private/GritCalculator';
|
||||
|
||||
interface GritResultProps {
|
||||
answers: string[];
|
||||
}
|
||||
|
||||
const levelText = {
|
||||
low: '坚毅程度偏低',
|
||||
moderate: '坚毅程度中等',
|
||||
high: '坚毅程度较高',
|
||||
};
|
||||
|
||||
const levelDescription = {
|
||||
low: '你当前在长期目标上的持续投入或兴趣稳定性可能偏弱。更适合从目标拆小、减少干扰、明确反馈开始,而不是单靠意志力硬撑。',
|
||||
moderate: '你具备一定的坚持能力,但在目标很长期、反馈很慢或兴趣变化较快时,可能会出现波动。',
|
||||
high: '你通常能围绕长期目标持续努力,也较不容易被短期挫折带偏。继续保留调整目标的弹性会更稳。',
|
||||
};
|
||||
|
||||
function width(value: number) {
|
||||
return `${Math.max(0, Math.min(100, ((value - 1) / 4) * 100))}%`;
|
||||
}
|
||||
|
||||
export function GritResult({ answers }: GritResultProps) {
|
||||
const results = calculateGritResults(answers);
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-6">
|
||||
<div className="border bg-white p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold mb-4">坚毅量表结果</h3>
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
<MetricCard title="总平均分" value={results.totalAverage.toFixed(2)} />
|
||||
<MetricCard
|
||||
title="努力坚持"
|
||||
value={results.perseveranceAverage.toFixed(2)}
|
||||
/>
|
||||
<MetricCard
|
||||
title="兴趣稳定"
|
||||
value={results.consistencyAverage.toFixed(2)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<BarCard title="努力坚持" value={results.perseveranceAverage} />
|
||||
<BarCard title="兴趣稳定" value={results.consistencyAverage} />
|
||||
</div>
|
||||
|
||||
<div className="border bg-blue-50 p-6 text-blue-900 shadow-sm">
|
||||
<h3 className="text-lg font-semibold mb-3">{levelText[results.level]}</h3>
|
||||
<p className="text-sm">{levelDescription[results.level]}</p>
|
||||
</div>
|
||||
|
||||
<div className="border bg-gray-50 p-4 text-sm text-gray-700">
|
||||
注:Grit 结果描述的是长期目标中的坚持和稳定倾向,不代表能力高低,也不意味着所有目标都应该坚持到底。
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface MetricCardProps {
|
||||
title: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
function MetricCard({ title, value }: MetricCardProps) {
|
||||
return (
|
||||
<div className="rounded-lg bg-gray-50 p-4 text-center">
|
||||
<div className="text-sm text-muted-foreground">{title}</div>
|
||||
<div className="mt-1 text-2xl font-semibold text-indigo-600">
|
||||
{value}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">/ 5</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function BarCard({ title, value }: { title: string; value: number }) {
|
||||
return (
|
||||
<div className="rounded-lg border bg-white p-5 shadow-sm">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h4 className="font-semibold">{title}</h4>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{value.toFixed(2)} / 5
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-2 overflow-hidden rounded-full bg-gray-100">
|
||||
<div
|
||||
className="h-full rounded-full bg-emerald-500"
|
||||
style={{ width: width(value) }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user