feat(ui): refresh panel landing with user center summary (#352)
This commit is contained in:
parent
f414e96508
commit
af124368f0
@ -44,8 +44,8 @@ export default function Header({ onMenu }: HeaderProps) {
|
||||
|
||||
<div className="flex flex-1 items-center justify-end gap-4 md:justify-between">
|
||||
<div className="hidden flex-col text-sm text-gray-500 md:flex">
|
||||
<span className="font-semibold text-gray-900">XControl Control Center</span>
|
||||
<span>Unified governance for admins and end users</span>
|
||||
<span className="font-semibold text-gray-900">XControl User Center</span>
|
||||
<span>Personalized access across every service touchpoint</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className={`rounded-full px-3 py-1 text-xs font-semibold ${badgeClasses}`}>{statusBadge}</span>
|
||||
|
||||
@ -32,58 +32,58 @@ interface NavSection {
|
||||
|
||||
const navSections: NavSection[] = [
|
||||
{
|
||||
title: 'Overview',
|
||||
title: '用户中心',
|
||||
items: [
|
||||
{
|
||||
href: '/panel',
|
||||
label: 'Dashboard',
|
||||
description: 'Control center snapshot',
|
||||
description: '专属于你的信息总览',
|
||||
icon: Home,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Admin Toolkit',
|
||||
title: '功能特性',
|
||||
items: [
|
||||
{
|
||||
href: '/panel/agent',
|
||||
label: 'Agents',
|
||||
description: 'Manage runtime nodes',
|
||||
description: '管理运行时节点',
|
||||
icon: Server,
|
||||
},
|
||||
{
|
||||
href: '/panel/api',
|
||||
label: 'APIs',
|
||||
description: 'Observe backend services',
|
||||
description: '洞察后端服务',
|
||||
icon: Code,
|
||||
},
|
||||
{
|
||||
href: '/panel/subscription',
|
||||
label: 'Subscription',
|
||||
description: 'Billing & plan controls',
|
||||
description: '套餐与计费控制',
|
||||
icon: CreditCard,
|
||||
},
|
||||
{
|
||||
href: '/panel/xray',
|
||||
label: 'XRay',
|
||||
description: 'Inspect network policies',
|
||||
description: '审视网络策略',
|
||||
icon: Search,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Identity & Access',
|
||||
title: '权限设置',
|
||||
items: [
|
||||
{
|
||||
href: '/panel/account',
|
||||
label: 'Accounts',
|
||||
description: 'Directory & MFA settings',
|
||||
description: '目录与多因素设置',
|
||||
icon: User,
|
||||
},
|
||||
{
|
||||
href: '/panel/ldp',
|
||||
label: 'LDP',
|
||||
description: 'Low-latency identity plane',
|
||||
description: '低时延身份平面',
|
||||
icon: Shield,
|
||||
},
|
||||
],
|
||||
@ -104,8 +104,8 @@ export default function Sidebar({ className = '', onNavigate }: SidebarProps) {
|
||||
<aside className={`flex h-full w-72 flex-col gap-6 border-r border-gray-200 bg-white/90 p-6 shadow-lg backdrop-blur ${className}`}>
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-purple-600">XControl</p>
|
||||
<h2 className="text-lg font-bold text-gray-900">Control Center</h2>
|
||||
<p className="text-sm text-gray-500">Switch between admin and self-service spaces.</p>
|
||||
<h2 className="text-lg font-bold text-gray-900">User Center</h2>
|
||||
<p className="text-sm text-gray-500">在同一处掌控权限与功能特性。</p>
|
||||
</div>
|
||||
|
||||
<nav className="flex flex-1 flex-col gap-6 overflow-y-auto">
|
||||
|
||||
115
ui/homepage/app/panel/components/UserOverview.tsx
Normal file
115
ui/homepage/app/panel/components/UserOverview.tsx
Normal file
@ -0,0 +1,115 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { Copy } from 'lucide-react'
|
||||
|
||||
import Card from './Card'
|
||||
import { useUser } from '@lib/userStore'
|
||||
|
||||
function resolveDisplayName(
|
||||
user: {
|
||||
name?: string
|
||||
username: string
|
||||
email: string
|
||||
} | null,
|
||||
) {
|
||||
if (!user) {
|
||||
return '访客'
|
||||
}
|
||||
|
||||
if (user.name && user.name.trim().length > 0) {
|
||||
return user.name.trim()
|
||||
}
|
||||
|
||||
if (user.username && user.username.trim().length > 0) {
|
||||
return user.username.trim()
|
||||
}
|
||||
|
||||
return user.email
|
||||
}
|
||||
|
||||
export default function UserOverview() {
|
||||
const { user, isLoading } = useUser()
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const displayName = useMemo(() => resolveDisplayName(user), [user])
|
||||
const uuid = user?.id ?? '—'
|
||||
const username = user?.username ?? '—'
|
||||
const email = user?.email ?? '—'
|
||||
|
||||
const handleCopy = useCallback(async () => {
|
||||
if (!user?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof navigator !== 'undefined' && navigator.clipboard && 'writeText' in navigator.clipboard) {
|
||||
await navigator.clipboard.writeText(user.id)
|
||||
} else {
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.value = user.id
|
||||
textarea.style.position = 'fixed'
|
||||
textarea.style.opacity = '0'
|
||||
document.body.appendChild(textarea)
|
||||
textarea.focus()
|
||||
textarea.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(textarea)
|
||||
}
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
} catch (error) {
|
||||
console.warn('Failed to copy UUID', error)
|
||||
}
|
||||
}, [user?.id])
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">用户中心</h1>
|
||||
<p className="mt-2 text-sm text-gray-600">
|
||||
{isLoading ? '正在加载你的专属空间…' : user ? `欢迎回来,${displayName}。` : '请登录后解锁属于你的用户中心。'}
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-gray-500">
|
||||
UUID 是你在 XControl 中的唯一身份凭证,后续的所有服务都与它神秘地关联在一起。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<Card>
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-purple-600">UUID</p>
|
||||
<p className="mt-1 break-all text-base font-medium text-gray-900">{uuid}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCopy}
|
||||
disabled={!user?.id}
|
||||
className="inline-flex items-center gap-2 rounded-full border border-gray-300 px-3 py-1 text-xs font-medium text-gray-700 transition hover:border-purple-400 hover:text-purple-600 disabled:cursor-not-allowed disabled:border-gray-200 disabled:text-gray-400"
|
||||
aria-label="复制 UUID"
|
||||
>
|
||||
<Copy className="h-3.5 w-3.5" />
|
||||
{copied ? '已复制' : '复制'}
|
||||
</button>
|
||||
</div>
|
||||
<p className="mt-3 text-xs text-gray-500">
|
||||
这是一串只属于你的身份指纹,让平台中的每项服务都能准确识别你。
|
||||
</p>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-purple-600">UserName</p>
|
||||
<p className="mt-1 text-base font-medium text-gray-900">{username}</p>
|
||||
<p className="mt-3 text-xs text-gray-500">面向系统的登录凭据,展示给自动化流程与团队成员。</p>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-purple-600">UserEmail</p>
|
||||
<p className="mt-1 break-all text-base font-medium text-gray-900">{email}</p>
|
||||
<p className="mt-3 text-xs text-gray-500">用来接收通知、验证操作,并保持与你的 UUID 一致的信任链路。</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,34 +1,7 @@
|
||||
export const dynamic = 'error'
|
||||
|
||||
import Card from './components/Card'
|
||||
import UserOverview from './components/UserOverview'
|
||||
|
||||
export default function PanelHome() {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Dashboard</h1>
|
||||
<p className="mt-2 text-sm text-gray-600">
|
||||
Welcome to the XControl control center. Switch between administrator modules and self-service experiences to manage
|
||||
your platform with confidence.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<Card>
|
||||
<h2 className="text-lg font-semibold text-gray-900">Administrator modules</h2>
|
||||
<p className="mt-2 text-sm text-gray-600">
|
||||
Toggle core services, observe infrastructure health, and govern network gateways. Each module mirrors the original
|
||||
admin panel layout so existing workflows continue to work.
|
||||
</p>
|
||||
</Card>
|
||||
<Card>
|
||||
<h2 className="text-lg font-semibold text-gray-900">Self-service experiences</h2>
|
||||
<p className="mt-2 text-sm text-gray-600">
|
||||
Empower end users with password resets, MFA configuration, and delegated group management without leaving the
|
||||
homepage theme.
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
return <UserOverview />
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user