Files
2026-06-22 22:59:01 +02:00

134 lines
4.7 KiB
TypeScript

'use client';
import {
calculateSchwartzResults,
SchwartzHigherOrder,
SchwartzValue,
} from '../../test/private/SchwartzCalculator';
interface SchwartzResultProps {
answers: string[];
}
const valueDescriptions: Record<SchwartzValue, string> = {
selfDirection: '重视独立思考、自由选择和创造。',
stimulation: '重视新奇、挑战、变化和兴奋体验。',
hedonism: '重视愉悦、享受和积极体验。',
achievement: '重视能力表现、努力成果和外部认可。',
power: '重视影响力、资源、地位和掌控感。',
security: '重视稳定、安全、健康和生活保障。',
conformity: '重视规则、克制和对他人影响的边界。',
tradition: '重视文化、家庭、仪式和既有传承。',
benevolence: '重视照顾亲近的人、忠诚和可靠支持。',
universalism: '重视公平、包容、自然和更广泛的人群福祉。',
};
const higherOrderDescriptions: Record<SchwartzHigherOrder, string> = {
opennessToChange: '偏向自由、探索、变化和个人选择。',
conservation: '偏向秩序、稳定、规范和连续性。',
selfEnhancement: '偏向成就、影响力和个人资源增长。',
selfTranscendence: '偏向关怀、公平、包容和超越个人利益。',
};
function width(score: number) {
return `${Math.max(0, Math.min(100, ((score - 1) / 4) * 100))}%`;
}
export function SchwartzResult({ answers }: SchwartzResultProps) {
const results = calculateSchwartzResults(answers);
const topValues = results.rankedValues.slice(0, 3);
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">Schwartz 价值观结果</h3>
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
{topValues.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">
主要价值组合:{topValues.map((item) => item.name).join(' / ')}
</h3>
<p className="text-sm">
价值观结果更适合看相对优先级,而不是单个分数高低。你的高分价值通常会影响职业选择、关系边界、生活节奏和长期目标。
</p>
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
{results.rankedHigherOrders.map((item) => (
<ScoreCard
key={item.id}
title={item.name}
score={item.score}
description={higherOrderDescriptions[item.id]}
color="bg-indigo-500"
/>
))}
</div>
<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-2">
{results.rankedValues.map((item) => (
<ScoreCard
key={item.id}
title={item.name}
score={item.score}
description={valueDescriptions[item.id]}
color="bg-emerald-500"
/>
))}
</div>
</div>
<div className="border bg-gray-50 p-4 text-sm text-gray-700">
注:价值观不是好坏评价,而是优先级。相对冲突的价值同时高分时,实际选择中可能更需要明确场景和取舍。
</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-2xl 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>
);
}