From 13840754ad5ac87923dc9c7b314f95edccff3aa6 Mon Sep 17 00:00:00 2001 From: yun-zhi-ztl <15071461069@163.com> Date: Sun, 15 Mar 2026 13:44:07 +0800 Subject: [PATCH] feat(dashboard): add back navigation for subpages --- web/src/i18n/locales/en.json | 1 + web/src/i18n/locales/zh.json | 1 + web/src/pages/dashboard/my-namespaces.tsx | 13 ++++---- web/src/pages/dashboard/my-skills.tsx | 17 +++++----- web/src/pages/dashboard/namespace-members.tsx | 8 +++-- web/src/pages/dashboard/namespace-reviews.tsx | 11 +++---- web/src/pages/dashboard/promotions.tsx | 6 ++-- web/src/pages/dashboard/publish.tsx | 6 ++-- web/src/pages/dashboard/reviews.tsx | 6 ++-- web/src/pages/dashboard/stars.tsx | 6 ++-- web/src/pages/dashboard/tokens.tsx | 9 +++--- .../components/dashboard-page-header.tsx | 31 +++++++++++++++++++ 12 files changed, 72 insertions(+), 43 deletions(-) create mode 100644 web/src/shared/components/dashboard-page-header.tsx diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index b75ff53f..00f553c9 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -172,6 +172,7 @@ "dashboard": { "title": "Dashboard", "subtitle": "Manage your account and API Tokens", + "backToDashboard": "Back to Dashboard", "userInfo": "User Info", "userInfoDesc": "Your account details", "loginVia": "Logged in via {{provider}}", diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json index 1f5eee18..2abbb441 100644 --- a/web/src/i18n/locales/zh.json +++ b/web/src/i18n/locales/zh.json @@ -172,6 +172,7 @@ "dashboard": { "title": "Dashboard", "subtitle": "管理你的账户和 API Tokens", + "backToDashboard": "返回控制台", "userInfo": "用户信息", "userInfoDesc": "你的账户详情", "loginVia": "通过 {{provider}} 登录", diff --git a/web/src/pages/dashboard/my-namespaces.tsx b/web/src/pages/dashboard/my-namespaces.tsx index 46210b30..b7641c26 100644 --- a/web/src/pages/dashboard/my-namespaces.tsx +++ b/web/src/pages/dashboard/my-namespaces.tsx @@ -4,6 +4,7 @@ import { Button } from '@/shared/ui/button' import { Card } from '@/shared/ui/card' import { NamespaceBadge } from '@/shared/components/namespace-badge' import { EmptyState } from '@/shared/components/empty-state' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' import { useMyNamespaces } from '@/shared/hooks/use-skill-queries' export function MyNamespacesPage() { @@ -37,13 +38,11 @@ export function MyNamespacesPage() { return (
-
-
-

{t('myNamespaces.title')}

-

{t('myNamespaces.subtitle')}

-
- -
+ {t('myNamespaces.create')}} + /> {namespaces && namespaces.length > 0 ? (
diff --git a/web/src/pages/dashboard/my-skills.tsx b/web/src/pages/dashboard/my-skills.tsx index 1278858a..5a94b3d4 100644 --- a/web/src/pages/dashboard/my-skills.tsx +++ b/web/src/pages/dashboard/my-skills.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { Button } from '@/shared/ui/button' import { Card } from '@/shared/ui/card' import { EmptyState } from '@/shared/components/empty-state' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' import { useMySkills } from '@/shared/hooks/use-skill-queries' import { formatCompactCount } from '@/shared/lib/number-format' @@ -47,15 +48,15 @@ export function MySkillsPage() { return (
-
-
-

{t('mySkills.title')}

-

{t('mySkills.subtitle')}

-
- -
+ + )} + /> {skills && skills.length > 0 ? (
diff --git a/web/src/pages/dashboard/namespace-members.tsx b/web/src/pages/dashboard/namespace-members.tsx index 6081a7f1..b7af1374 100644 --- a/web/src/pages/dashboard/namespace-members.tsx +++ b/web/src/pages/dashboard/namespace-members.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { NamespaceHeader } from '@/features/namespace/namespace-header' import { Button } from '@/shared/ui/button' import { Card } from '@/shared/ui/card' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' import { useNamespaceDetail, useNamespaceMembers } from '@/shared/hooks/use-skill-queries' export function NamespaceMembersPage() { @@ -34,11 +35,14 @@ export function NamespaceMembersPage() { return (
+
-
-

{t('members.title')}

+
diff --git a/web/src/pages/dashboard/namespace-reviews.tsx b/web/src/pages/dashboard/namespace-reviews.tsx index 250e8471..16f4cf7a 100644 --- a/web/src/pages/dashboard/namespace-reviews.tsx +++ b/web/src/pages/dashboard/namespace-reviews.tsx @@ -4,6 +4,7 @@ import { Card } from '@/shared/ui/card' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/shared/ui/tabs' import { useNamespaceDetail } from '@/shared/hooks/use-skill-queries' import { useReviewList } from '@/features/review/use-review-list' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' function ReviewListSection({ namespaceId }: { namespaceId?: number }) { const { t } = useTranslation() @@ -56,12 +57,10 @@ export function NamespaceReviewsPage() { return (
-
-

{t('nsReviews.title')}

-

- {namespace ? t('nsReviews.reviewsFor', { name: namespace.displayName }) : t('nsReviews.loadingNamespace')} -

-
+
) diff --git a/web/src/pages/dashboard/promotions.tsx b/web/src/pages/dashboard/promotions.tsx index 446ad898..d3a2e5d5 100644 --- a/web/src/pages/dashboard/promotions.tsx +++ b/web/src/pages/dashboard/promotions.tsx @@ -5,6 +5,7 @@ import { Button } from '@/shared/ui/button' import { Card } from '@/shared/ui/card' import { Input } from '@/shared/ui/input' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/shared/ui/tabs' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' function PromotionSection({ status }: { status: 'PENDING' | 'APPROVED' | 'REJECTED' }) { const { t, i18n } = useTranslation() @@ -70,10 +71,7 @@ export function PromotionsPage() { const { t } = useTranslation() return (
-
-

{t('promotions.title')}

-

{t('promotions.subtitle')}

-
+ {t('promotions.tabPending')} diff --git a/web/src/pages/dashboard/publish.tsx b/web/src/pages/dashboard/publish.tsx index b3ee3790..febfb8e0 100644 --- a/web/src/pages/dashboard/publish.tsx +++ b/web/src/pages/dashboard/publish.tsx @@ -7,6 +7,7 @@ import { Select } from '@/shared/ui/select' import { Label } from '@/shared/ui/label' import { Card } from '@/shared/ui/card' import { useMyNamespaces, usePublishSkill } from '@/shared/hooks/use-skill-queries' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' import { toast } from '@/shared/lib/toast' import { ApiError } from '@/api/client' @@ -73,10 +74,7 @@ export function PublishPage() { return (
-
-

{t('publish.title')}

-

{t('publish.subtitle')}

-
+
diff --git a/web/src/pages/dashboard/reviews.tsx b/web/src/pages/dashboard/reviews.tsx index 5ce4225b..da5b9fc5 100644 --- a/web/src/pages/dashboard/reviews.tsx +++ b/web/src/pages/dashboard/reviews.tsx @@ -11,6 +11,7 @@ import { TableRow, } from '@/shared/ui/table' import { useReviewList } from '@/features/review/use-review-list' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' export function ReviewsPage() { const { t, i18n } = useTranslation() @@ -94,10 +95,7 @@ export function ReviewsPage() { return (
-
-

{t('reviews.title')}

-

{t('reviews.subtitle')}

-
+ diff --git a/web/src/pages/dashboard/stars.tsx b/web/src/pages/dashboard/stars.tsx index 5a570dc1..7e0e59f5 100644 --- a/web/src/pages/dashboard/stars.tsx +++ b/web/src/pages/dashboard/stars.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { SkillCard } from '@/features/skill/skill-card' import { useMyStars } from '@/shared/hooks/use-skill-queries' import { Card } from '@/shared/ui/card' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' export function MyStarsPage() { const { t } = useTranslation() @@ -21,10 +22,7 @@ export function MyStarsPage() { return (
-
-

{t('stars.title')}

-

{t('stars.subtitle')}

-
+ {!skills || skills.length === 0 ? ( {t('stars.empty')} diff --git a/web/src/pages/dashboard/tokens.tsx b/web/src/pages/dashboard/tokens.tsx index 034e0f96..5f8a478e 100644 --- a/web/src/pages/dashboard/tokens.tsx +++ b/web/src/pages/dashboard/tokens.tsx @@ -1,14 +1,15 @@ import { useTranslation } from 'react-i18next' import { TokenList } from '@/features/token/token-list' +import { DashboardPageHeader } from '@/shared/components/dashboard-page-header' export function TokensPage() { const { t } = useTranslation() return (
-
-

{t('tokens.pageTitle')}

-

{t('tokens.pageSubtitle')}

-
+
) diff --git a/web/src/shared/components/dashboard-page-header.tsx b/web/src/shared/components/dashboard-page-header.tsx new file mode 100644 index 00000000..33715403 --- /dev/null +++ b/web/src/shared/components/dashboard-page-header.tsx @@ -0,0 +1,31 @@ +import { useNavigate } from '@tanstack/react-router' +import { ArrowLeft } from 'lucide-react' +import { useTranslation } from 'react-i18next' +import { Button } from '@/shared/ui/button' + +interface DashboardPageHeaderProps { + title: string + subtitle?: string + actions?: React.ReactNode +} + +export function DashboardPageHeader({ title, subtitle, actions }: DashboardPageHeaderProps) { + const { t } = useTranslation() + const navigate = useNavigate() + + return ( +
+ +
+
+

{title}

+ {subtitle ?

{subtitle}

: null} +
+ {actions} +
+
+ ) +}