fix: refine my skills empty states

This commit is contained in:
yun-zhi-ztl 2026-03-19 17:10:09 +08:00
parent 296c713652
commit 4d827204bb
5 changed files with 48 additions and 4 deletions

View file

@ -339,6 +339,14 @@
"promotionErrorTitle": "Failed to submit promotion request",
"emptyTitle": "No skills yet",
"emptyDescription": "Start publishing your first skill",
"emptyFilteredTitle": "No skills match this filter",
"emptyFilteredDescription": {
"PENDING_REVIEW": "There are no skills waiting for review right now.",
"PUBLISHED": "There are no published skills right now.",
"REJECTED": "There are no rejected skills right now.",
"ARCHIVED": "There are no archived skills right now.",
"HIDDEN": "There are no hidden skills right now."
},
"publishSkill": "Publish Skill"
},
"myNamespaces": {

View file

@ -339,6 +339,14 @@
"promotionErrorTitle": "提交提升申请失败",
"emptyTitle": "还没有技能",
"emptyDescription": "开始发布你的第一个技能吧",
"emptyFilteredTitle": "当前筛选下没有技能",
"emptyFilteredDescription": {
"PENDING_REVIEW": "当前没有处于待审核状态的技能。",
"PUBLISHED": "当前没有已发布的技能。",
"REJECTED": "当前没有已拒绝的技能。",
"ARCHIVED": "当前没有已归档的技能。",
"HIDDEN": "当前没有已隐藏的技能。"
},
"publishSkill": "发布技能"
},
"myNamespaces": {

View file

@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { getMySkillFilters } from './my-skill-filters'
import { getMySkillEmptyStateKey, getMySkillFilters } from './my-skill-filters'
describe('getMySkillFilters', () => {
it('returns lifecycle filters for regular users', () => {
@ -9,4 +9,18 @@ describe('getMySkillFilters', () => {
it('adds hidden filter for super admins', () => {
expect(getMySkillFilters(true)).toEqual(['ALL', 'PUBLISHED', 'HIDDEN', 'ARCHIVED'])
})
it('returns default empty-state copy for all skills', () => {
expect(getMySkillEmptyStateKey('ALL')).toEqual({
title: 'mySkills.emptyTitle',
description: 'mySkills.emptyDescription',
})
})
it('returns filter-specific empty-state copy for scoped filters', () => {
expect(getMySkillEmptyStateKey('PENDING_REVIEW')).toEqual({
title: 'mySkills.emptyFilteredTitle',
description: 'mySkills.emptyFilteredDescription.PENDING_REVIEW',
})
})
})

View file

@ -7,3 +7,16 @@ export function getMySkillFilters(isSuperAdmin: boolean): MySkillFilter[] {
return ['ALL', 'PENDING_REVIEW', 'PUBLISHED', 'REJECTED', 'ARCHIVED']
}
export function getMySkillEmptyStateKey(filter: MySkillFilter): { title: string; description: string } {
if (filter === 'ALL') {
return {
title: 'mySkills.emptyTitle',
description: 'mySkills.emptyDescription',
}
}
return {
title: 'mySkills.emptyFilteredTitle',
description: `mySkills.emptyFilteredDescription.${filter}`,
}
}

View file

@ -13,7 +13,7 @@ import { getHeadlineVersion, getPublishedVersion, getOwnerPreviewVersion, hasPen
import { formatCompactCount } from '@/shared/lib/number-format'
import { toast } from '@/shared/lib/toast'
import { ApiError } from '@/api/client'
import { getMySkillFilters, type MySkillFilter } from './my-skill-filters'
import { getMySkillEmptyStateKey, getMySkillFilters, type MySkillFilter } from './my-skill-filters'
const PAGE_SIZE = 10
@ -47,6 +47,7 @@ export function MySkillsPage() {
const skills = skillPage?.items ?? []
const totalPages = skillPage ? Math.max(Math.ceil(skillPage.total / skillPage.size), 1) : 1
const availableFilters = getMySkillFilters(hasRole('SUPER_ADMIN'))
const emptyStateKey = getMySkillEmptyStateKey(filter)
const archiveMutation = useArchiveSkill()
const unarchiveMutation = useUnarchiveSkill()
const withdrawMutation = useWithdrawSkillReview()
@ -366,8 +367,8 @@ export function MySkillsPage() {
</>
) : (
<EmptyState
title={t('mySkills.emptyTitle')}
description={t('mySkills.emptyDescription')}
title={t(emptyStateKey.title)}
description={t(emptyStateKey.description)}
action={
<Button size="lg" onClick={() => navigate({ to: '/dashboard/publish' })}>
{t('mySkills.publishSkill')}