feat: add standalone skill guidance modal
This commit is contained in:
parent
cae44c47cb
commit
572c433bbd
@ -825,7 +825,6 @@ export function ProfileSkillsInline({
|
||||
const [endorsementReason, setEndorsementReason] = useState("");
|
||||
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) => {
|
||||
@ -931,12 +930,12 @@ export function ProfileSkillsInline({
|
||||
<span>{title}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setHelpOpen((value) => !value)}
|
||||
onClick={() => setHelpOpen(true)}
|
||||
className="app-accent-text inline-flex h-5 w-5 items-center justify-center rounded-full transition hover:bg-[var(--surface-tertiary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--accent-primary)]"
|
||||
aria-label="Как правильно заполнять навыки"
|
||||
aria-label="Открыть справку о навыках"
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={helpOpen}
|
||||
aria-controls={helpId}
|
||||
title="Показать правила заполнения"
|
||||
title="Как работают навыки"
|
||||
>
|
||||
<CircleHelp size={14} strokeWidth={2} />
|
||||
</button>
|
||||
@ -946,23 +945,6 @@ export function ProfileSkillsInline({
|
||||
closeOnClickOutside
|
||||
>
|
||||
<div className="space-y-4">
|
||||
{helpOpen ? (
|
||||
<div
|
||||
id={helpId}
|
||||
className="app-surface-muted rounded-xl border border-[var(--border-subtle)] px-3 py-3 text-sm"
|
||||
>
|
||||
<p className="font-semibold text-[var(--foreground)]">Как заполнять навыки</p>
|
||||
<ul className="app-text-muted mt-2 space-y-1.5 text-xs leading-relaxed">
|
||||
<li>• Один навык — одна конкретная компетенция или технология.</li>
|
||||
<li>• Выбирайте существующее название из списка, если оно уже есть.</li>
|
||||
<li>• Не объединяйте несколько навыков и не указывайте должность или уровень владения.</li>
|
||||
</ul>
|
||||
<p className="app-text-muted mt-2 text-xs">
|
||||
Например: «Python», «1С», «Электромонтаж».
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="flex min-w-0 gap-2">
|
||||
<input
|
||||
list={listId}
|
||||
@ -1035,6 +1017,83 @@ export function ProfileSkillsInline({
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
isOpen={helpOpen}
|
||||
onClose={() => setHelpOpen(false)}
|
||||
title="Как работают навыки"
|
||||
size="sm"
|
||||
stackLevel={1}
|
||||
closeOnClickOutside
|
||||
>
|
||||
<div className="space-y-3 text-sm">
|
||||
<section className="app-surface-muted rounded-xl border border-[var(--border-subtle)] p-3">
|
||||
<h3 className="font-semibold text-[var(--foreground)]">Как добавлять</h3>
|
||||
<ul className="app-text-muted mt-2 space-y-1.5 text-xs leading-relaxed">
|
||||
<li>• Один навык — одна конкретная компетенция или технология.</li>
|
||||
<li>• Выбирайте существующее название, если оно уже есть в списке.</li>
|
||||
<li>• Не объединяйте навыки и не указывайте должность или уровень владения.</li>
|
||||
</ul>
|
||||
<p className="app-text-muted mt-2 text-xs">
|
||||
Например: «Python», «1С», «Электромонтаж».
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="app-surface-muted rounded-xl border border-[var(--border-subtle)] p-3">
|
||||
<h3 className="font-semibold text-[var(--foreground)]">Опыт и ранг</h3>
|
||||
<p className="app-text-muted mt-1 text-xs leading-relaxed">
|
||||
Ранг показывает личный уровень сотрудника в конкретном навыке. Опыт начисляется за завершённые задачи с этим навыком и подтверждения коллег.
|
||||
</p>
|
||||
<div className="mt-3 grid grid-cols-2 gap-1.5 text-xs sm:grid-cols-3">
|
||||
{[
|
||||
{ rank: "none" as const, label: "Без ранга", xp: "0 XP" },
|
||||
{ rank: "bronze" as const, label: "Бронза", xp: "100 XP" },
|
||||
{ rank: "silver" as const, label: "Серебро", xp: "300 XP" },
|
||||
{ rank: "gold" as const, label: "Золото", xp: "800 XP" },
|
||||
{ rank: "ruby" as const, label: "Рубин", xp: "1 800 XP" },
|
||||
{ rank: "diamond" as const, label: "Бриллиант", xp: "4 000 XP" },
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.rank}
|
||||
className="app-surface flex min-w-0 items-center gap-2 rounded-lg border border-[var(--border-subtle)] px-2.5 py-2"
|
||||
>
|
||||
<SkillRankMark rank={item.rank} />
|
||||
<div className="min-w-0">
|
||||
<p className="truncate font-medium text-[var(--foreground)]">{item.label}</p>
|
||||
<p className="app-text-muted text-[10px]">{item.xp}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="app-text-muted mt-2 text-[11px] leading-relaxed">
|
||||
Завершённая задача даёт 25 XP. Подтверждение коллеги — 5–15 XP в зависимости от его роли.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="app-surface-muted rounded-xl border border-[var(--border-subtle)] p-3">
|
||||
<h3 className="font-semibold text-[var(--foreground)]">Редкость</h3>
|
||||
<p className="app-text-muted mt-1 text-xs leading-relaxed">
|
||||
Редкость относится к самому навыку и показывает, насколько редко он встречается среди подтверждённых обладателей в компании. Ранг при этом остаётся личным для каждого сотрудника.
|
||||
</p>
|
||||
<div className="mt-2 flex flex-wrap gap-1.5">
|
||||
{[
|
||||
{ rarity: "legendary" as const, label: "Легендарный · 1" },
|
||||
{ rarity: "epic" as const, label: "Эпический · 2–3" },
|
||||
{ rarity: "rare" as const, label: "Редкий · 4–9" },
|
||||
{ rarity: "uncommon" as const, label: "Необычный · 10–24" },
|
||||
{ rarity: "common" as const, label: "Обычный · 25+" },
|
||||
].map((item) => (
|
||||
<span
|
||||
key={item.rarity}
|
||||
className={`rounded-full px-2 py-1 text-[11px] font-semibold ${skillRarityBadgeStyles[item.rarity]}`}
|
||||
>
|
||||
{item.label}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
isOpen={progressOpen}
|
||||
onClose={() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user