141 lines
5.4 KiB
TypeScript
141 lines
5.4 KiB
TypeScript
'use client';
|
|
|
|
import { calculateVIAResults, VIAStrength, VIAVirtue } from '../../test/private/VIACalculator';
|
|
|
|
interface VIAResultProps {
|
|
answers: string[];
|
|
}
|
|
|
|
const strengthDescriptions: Record<VIAStrength, string> = {
|
|
creativity: "用新颖有效的方式思考和行动。",
|
|
curiosity: "主动探索未知,持续提问和观察。",
|
|
judgment: "开放评估证据,避免草率判断。",
|
|
loveOfLearning: "从学习和掌握新知识中获得满足。",
|
|
perspective: "能整合经验,为自己或他人提供有用视角。",
|
|
bravery: "在压力、风险或恐惧中坚持重要行动。",
|
|
perseverance: "面对困难仍持续完成目标。",
|
|
honesty: "真实、可靠,不依赖伪装获得认可。",
|
|
zest: "带着能量、投入和生命力行动。",
|
|
love: "重视亲密、信任和双向关心。",
|
|
kindness: "愿意照顾他人并提供实际帮助。",
|
|
socialIntelligence: "理解他人情绪、动机和场景需求。",
|
|
teamwork: "愿意合作并承担团队责任。",
|
|
fairness: "重视公正、平等和不偏袒。",
|
|
leadership: "组织、协调并带动群体前进。",
|
|
forgiveness: "能在合适时机放下怨气,重新看待关系。",
|
|
humility: "不过度夸大自己,承认仍需学习。",
|
|
prudence: "行动前考虑风险、后果和边界。",
|
|
selfRegulation: "管理冲动、情绪和行为节奏。",
|
|
appreciation: "感受自然、艺术和卓越表现中的美。",
|
|
gratitude: "看见并珍惜已经拥有和被给予的东西。",
|
|
hope: "相信未来可以改善,并愿意为此行动。",
|
|
humor: "用轻松方式缓和压力、连接他人。",
|
|
spirituality: "感到自己与更大的意义、信念或整体有关联。",
|
|
};
|
|
|
|
const virtueDescriptions: Record<VIAVirtue, string> = {
|
|
wisdom: "认知探索、学习、判断和形成视角的优势。",
|
|
courage: "面对困难仍行动、坚持和保持真实的优势。",
|
|
humanity: "建立亲密、善意和人际理解的优势。",
|
|
justice: "合作、公平和组织群体行动的优势。",
|
|
temperance: "克制、审慎、谦逊和修复关系的优势。",
|
|
transcendence: "连接意义、美、希望、感恩和幽默的优势。",
|
|
};
|
|
|
|
function width(score: number) {
|
|
return `${Math.max(0, Math.min(100, ((score - 1) / 4) * 100))}%`;
|
|
}
|
|
|
|
export function VIAResult({ answers }: VIAResultProps) {
|
|
const results = calculateVIAResults(answers);
|
|
const signature = results.rankedStrengths.slice(0, 5);
|
|
|
|
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">VIA 性格优势结果</h3>
|
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-5">
|
|
{signature.map((item, index) => (
|
|
<MetricCard key={item.id} title={`优势 ${index + 1}`} value={item.name} score={item.score.toFixed(2)} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border bg-blue-50 p-6 text-blue-900 shadow-sm">
|
|
<h3 className="text-lg font-semibold mb-3">
|
|
标志性优势:{signature.map((item) => item.name).join(" / ")}
|
|
</h3>
|
|
<p className="text-sm">
|
|
VIA结果重点看你最自然、最常调用的优势。低排序项目不等于弱点,只表示它们不是当前最突出的表达方式。
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
{results.rankedVirtues.map((item) => (
|
|
<ScoreCard
|
|
key={item.id}
|
|
title={item.name}
|
|
score={item.score}
|
|
description={virtueDescriptions[item.id]}
|
|
color="bg-indigo-500"
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="border bg-white p-6 shadow-sm">
|
|
<h3 className="text-lg font-semibold mb-4">24项性格优势</h3>
|
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
{results.rankedStrengths.map((item) => (
|
|
<ScoreCard
|
|
key={item.id}
|
|
title={item.name}
|
|
score={item.score}
|
|
description={strengthDescriptions[item.id]}
|
|
color="bg-emerald-500"
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border bg-gray-50 p-4 text-sm text-gray-700">
|
|
注:本测评用于性格优势自评,不是官方VIA-IS题库,也不用于诊断。建议把前5项优势用于学习、职业和关系策略设计。
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function MetricCard({ title, value, score }: { title: string; value: string; score: string }) {
|
|
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-xl font-semibold text-indigo-600">{value}</div>
|
|
<div className="text-xs text-muted-foreground">{score} / 5</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ScoreCard({
|
|
title,
|
|
score,
|
|
description,
|
|
color,
|
|
}: {
|
|
title: string;
|
|
score: number;
|
|
description: string;
|
|
color: string;
|
|
}) {
|
|
return (
|
|
<div className="border bg-white p-5 shadow-sm">
|
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
<h4 className="font-semibold">{title}</h4>
|
|
<span className="text-sm text-muted-foreground">{score.toFixed(2)} / 5</span>
|
|
</div>
|
|
<div className="h-2 overflow-hidden rounded-full bg-gray-100">
|
|
<div className={`h-full rounded-full ${color}`} style={{ width: width(score) }} />
|
|
</div>
|
|
<p className="mt-3 text-sm text-gray-700">{description}</p>
|
|
</div>
|
|
);
|
|
}
|