fix: clarify skill rank ordering and rarity

This commit is contained in:
lizerk 2026-08-25 14:20:05 +03:00
parent ae4eb4696a
commit cae44c47cb

View File

@ -67,6 +67,45 @@ const skillRarityStyles: Record<SkillRarity, string> = {
legendary: "border-amber-400/80",
};
const skillRarityBadgeStyles: Record<SkillRarity, string> = {
unrated: "bg-slate-500/10 text-slate-400",
common: "bg-slate-500/15 text-slate-300",
uncommon: "bg-emerald-500/15 text-emerald-300",
rare: "bg-sky-500/15 text-sky-300",
epic: "bg-violet-500/15 text-violet-300",
legendary: "bg-amber-400/15 text-amber-300",
};
const skillRankOrder: Record<SkillRank, number> = {
none: 0,
bronze: 1,
silver: 2,
gold: 3,
ruby: 4,
diamond: 5,
};
const skillRarityOrder: Record<SkillRarity, number> = {
unrated: 0,
common: 1,
uncommon: 2,
rare: 3,
epic: 4,
legendary: 5,
};
function sortProfileSkills(skills: Skill[]) {
return [...skills].sort((left, right) => {
const rankDifference = skillRankOrder[right.rank || "none"] - skillRankOrder[left.rank || "none"];
if (rankDifference) return rankDifference;
const experienceDifference = (right.experience || 0) - (left.experience || 0);
if (experienceDifference) return experienceDifference;
const rarityDifference = skillRarityOrder[right.rarity || "unrated"] - skillRarityOrder[left.rarity || "unrated"];
if (rarityDifference) return rarityDifference;
return left.name.localeCompare(right.name, "ru");
});
}
function SkillRankMark({ rank = "none", size = 14 }: { rank?: SkillRank; size?: number }) {
const props = { size, strokeWidth: 2.2, "aria-hidden": true };
if (rank === "bronze") return <Shield {...props} className="text-amber-700" />;
@ -787,6 +826,7 @@ export function ProfileSkillsInline({
const [endorsementSaving, setEndorsementSaving] = useState(false);
const listId = `${title.toLowerCase().replace(/\s+/g, "-")}-skills-list`;
const helpId = `${listId}-help`;
const sortedSkills = sortProfileSkills(skills);
const openSkillProgress = async (skill: Skill) => {
setProgressOpen(true);
@ -832,12 +872,15 @@ export function ProfileSkillsInline({
<div>
<div className="flex min-w-0 items-center gap-2">
<HorizontalChipScroller
key={sortedSkills
.map((skill) => `${skill.id}:${skill.rank}:${skill.experience}:${skill.rarity}`)
.join("|")}
className="min-w-0 flex-1"
ariaLabel="Навыки сотрудника"
fadeColor="var(--surface-primary)"
>
{skills.length ? (
skills.map((skill) => (
{sortedSkills.length ? (
sortedSkills.map((skill) => (
<button
key={skill.id}
type="button"
@ -846,9 +889,17 @@ export function ProfileSkillsInline({
skillRarityStyles[skill.rarity || "unrated"]
}`}
title={`${skill.rank_display || "Без ранга"} · ${skill.rarity_display || "Редкость не определена"}`}
aria-label={`${skill.name}. Ранг: ${skill.rank_display || "Без ранга"}. Редкость: ${skill.rarity_display || "Не определена"}`}
>
<SkillRankMark rank={skill.rank} />
{skill.name}
<span>{skill.name}</span>
<span
className={`rounded-full px-1.5 py-0.5 text-[10px] font-semibold leading-none ${
skillRarityBadgeStyles[skill.rarity || "unrated"]
}`}
>
{skill.rarity_display || "Не определена"}
</span>
</button>
))
) : (